আমি স্বাক্ষরবিহীন পূর্ণসংখ্যার বহুগুণ ওভারফ্লো কীভাবে সনাক্ত করব?


618

আমি C ++ একটি প্রোগ্রাম লিখছিলাম সব সমাধান খুঁজে বের করার একটি = , যেখানে একটি , এবং একসঙ্গে ভাবে সংখ্যা বসিয়ে ব্যবহার 0-9 ঠিক একবার। প্রোগ্রামের মান উপর কর্তিত একটি এবং , এবং এটি একটি অঙ্ক-কাউন্টিং রুটিন উপর প্রতিটি সময় দৌড়ে একটি , এবং একটি যদি ডিজিট শর্ত সন্তুষ্ট ছিল করো।

যাইহোক, কৃত্রিম সমাধান যখন উত্পন্ন করা যেতে পারে একটি পূর্ণসংখ্যা সীমা উপচে। আমি এই কোড ব্যবহার করে কোডটি পরীক্ষা করে শেষ করেছি:

unsigned long b, c, c_test;
...
c_test=c*b;         // Possible overflow
if (c_test/b != c) {/* There has been an overflow*/}
else c=c_test;      // No overflow

ওভারফ্লো পরীক্ষা করার আরও ভাল উপায় আছে? আমি জানি যে কিছু চিপগুলির অভ্যন্তরীণ পতাকা রয়েছে যা ওভারফ্লো হয় যখন সেট করা থাকে তবে আমি কখনও এটি সি বা সি ++ এর মাধ্যমে অ্যাক্সেস করতে দেখিনি।


সতর্কতা অবলম্বন করুন যে সাইন ইন করা int ওভারফ্লো সি এবং সি ++ এর মধ্যে অপরিবর্তিত আচরণ এবং তাই আপনাকে এটি প্রকৃত কারণ না করে সনাক্ত করতে হবে। যোগ করার পূর্বে স্বাক্ষরিত ইনট ওভারফ্লোর জন্য, সি / সি ++ তে স্বাক্ষরিত ওভারফ্লো সনাক্তকরণ দেখুন ।


21
এই বিষয়টিতে দরকারী হতে পারে এমন তথ্য: সিকর্ড দ্বারা "সি এবং সি ++ এ সুরক্ষিত কোডিং" এর অধ্যায় 5 - http://www.informit.com/content/images/0321335724/samplechapter/seacord_ch05.pdf সি ++ এর জন্য নিরাপদ শ্রেণীর ক্লাস - HTTP : //blogs.msdn.com/david_leblanc/archive/2008/09/30/safeint-3-on-codeplex.aspx - http://www.codeplex.com/SafeInt IntSafe গ্রন্থাগার সি এর জন্য: - [ ব্লগস.এমএসএনএন .কম / মাইকেল_হওয়ার্ড / আর্কাইভ
মাইকেল বুড়

3
সিকর্ডস সিকিউর কোডিং হ'ল দুর্দান্ত রিসোর্স, তবে ইন্টেজারলিব ব্যবহার করবেন না। Blog.regehr.org/archives/593 দেখুন ।
jww

32
Gcc সংকলক বিকল্প -ftrapv ফলে এটি (স্বাক্ষরিত) পূর্ণসংখ্যার ওভারফ্লোতে একটি SIGABRT তৈরি করবে। এখানে দেখুন ।
নিবট

1
এটি ওভারফ্লো প্রশ্নের উত্তর দেয় না, তবে সমস্যাটিতে আসার আর একটি উপায় হ'ল বিগনম লাইব্রেরি পছন্দ করা জিএমপি-র করা আপনার গ্যারান্টিযুক্ত যাতে সর্বদা পর্যাপ্ত নির্ভুলতা থাকে। আপনি সামনের দিকে পর্যাপ্ত পরিমাণে বরাদ্দ দিলে আপনাকে ওভারফ্লো সম্পর্কে চিন্তা করতে হবে না।
wrdieter

1
@ হেইডজিয়েক তার উত্তরে প্রদত্ত তথ্যগুলি আমি খুব ভালভাবে যা বলব তা অনেকটাই দুর্দান্ত। তবে, একটি সংযোজন সহ। আপনি এখন একটি গুনের জন্য ওভারফ্লাউন সনাক্তকরণের উপায়টি সম্ভবত দ্রুততম। এআরএম-তে যেমন আমি হেডজিকের উত্তরে মন্তব্য করেছি আপনি সংখ্যার র‌্যাঙ্ক নির্ধারণ করতে clzনির্দেশ বা __clz(unsigned)ফাংশনটি ব্যবহার করতে পারেন (যেখানে এর সর্বোচ্চ বিটটি রয়েছে)। যেহেতু আমি নিশ্চিত না যে এটি x86 বা x64 এ উপলব্ধ কিনা তা আমি অনুমান করব এবং বলব যে সর্বাধিক উল্লেখযোগ্য বিট সন্ধান করা নিকৃষ্টতম log(sizeof(int)*8)নির্দেশাবলী নেবে ।
ননসেন্সিকেল

উত্তর:


229

আমি দেখতে পাচ্ছি আপনি স্বাক্ষরবিহীন পূর্ণসংখ্যা ব্যবহার করছেন। সংজ্ঞা অনুসারে, সিতে (আমি সি +++ সম্পর্কে জানি না), স্বাক্ষরবিহীন গাণিতিকগুলি উপচে পড়ছে না ... সুতরাং, কমপক্ষে সি এর জন্য, আপনার বিন্দুটি মজবুত :)

স্বাক্ষরিত পূর্ণসংখ্যার সাথে একবার ওভারফ্লো হয়ে গেলে, অপরিজ্ঞাত আচরণ (ইউবি) ঘটেছিল এবং আপনার প্রোগ্রামটি যে কোনও কিছু করতে পারে (উদাহরণস্বরূপ: পরীক্ষাগুলি অনিবার্যভাবে রেন্ডার করুন)। 

#include <limits.h>

int a = <something>;
int x = <something>;
a += x;              /* UB */
if (a < 0) {         /* Unreliable test */
  /* ... */
}

একটি কনফার্মিং প্রোগ্রাম তৈরি করতে, বলা ওভারফ্লো উত্পাদন করার আগে আপনাকে ওভারফ্লো পরীক্ষা করতে হবে test পদ্ধতিটি স্বাক্ষরবিহীন পূর্ণসংখ্যার সাথেও ব্যবহার করা যেতে পারে:

// For addition
#include <limits.h>

int a = <something>;
int x = <something>;
if ((x > 0) && (a > INT_MAX - x)) /* `a + x` would overflow */;
if ((x < 0) && (a < INT_MIN - x)) /* `a + x` would underflow */;

// For subtraction
#include <limits.h>
int a = <something>;
int x = <something>;
if ((x < 0) && (a > INT_MAX + x)) /* `a - x` would overflow */;
if ((x > 0) && (a < INT_MIN + x)) /* `a - x` would underflow */;

// For multiplication
#include <limits.h>

int a = <something>;
int x = <something>;
// There may be a need to check for -1 for two's complement machines.
// If one number is -1 and another is INT_MIN, multiplying them we get abs(INT_MIN) which is 1 higher than INT_MAX
if ((a == -1) && (x == INT_MIN)) /* `a * x` can overflow */
if ((x == -1) && (a == INT_MIN)) /* `a * x` (or `a / x`) can overflow */
// general case
if (a > INT_MAX / x) /* `a * x` would overflow */;
if ((a < INT_MIN / x)) /* `a * x` would underflow */;

বিভাগ (ছাড়া জন্য INT_MINএবং -1বিশেষ ক্ষেত্রে), ওইখানে যাচ্ছে কোন সম্ভাবনা নয় INT_MINবা INT_MAX


97
স্বাক্ষরযুক্ত পূর্ণসংখ্যাগুলি সি ++ তে কঠোরভাবে উপচে পড়বে না (আইএসও / আইসিসি 14882: 2003 3.9.1.4)। প্রশ্নটিতে আমার 'ওভারফ্লো' এর ব্যবহারটি আরও উচ্চারণমূলক অর্থ ছিল, স্বাক্ষরযুক্ত প্রকারের সু-সংজ্ঞায়িত মোড়কে অন্তর্ভুক্ত করার উদ্দেশ্যে, যেহেতু আমি গাণিতিক ধনাত্মক পূর্ণসংখ্যার প্রতিনিধিত্বকারী স্বাক্ষরিত ints সম্পর্কে আগ্রহী ছিলাম, ধনাত্মক পূর্ণসংখ্যা 2 ^ 32 (বা 2 ^) 64)। গাণিতিক অসীম-আকারের পূর্ণসংখ্যা আচরণ থেকে বিচ্যুতি হিসাবে ওভারফ্লো এবং ভাষার একটি অপরিজ্ঞাত আচরণ হিসাবে ওভারফ্লো মধ্যে পার্থক্য খুব কমই স্পষ্ট করে বলে মনে হয়।
ক্রিস জনসন

15
এই পরীক্ষাটি করার দরকার নেই x >= 0- x > 0পর্যাপ্ত হবে (যদি x == 0, তবে x + aসুস্পষ্ট কারণে ওভারফ্লো করতে পারে না)।
ক্যাফে

2
@ পিএমজি, মানক থেকে কোনও সমর্থনকারী উদ্ধৃতি আছে?
পেসারিয়ার

5
আমি এই পদ্ধতির পছন্দ করি ... তবে সতর্কতা অবলম্বন করুন: গুণনের ওভারফ্লো সনাক্তকরণটি একটি ধনাত্মক x বলে ধরেছে। X == 0 এর ক্ষেত্রে এটি শূন্য সনাক্তকরণের দ্বারা ভাগ করা যায় এবং নেতিবাচক এক্সের জন্য এটি সর্বদা ভুলক্রমে ওভারফ্লো সনাক্ত করে।
ফ্রানজ ডি

4
if ((a < INT_MIN / x))পরীক্ষা অনেক দেরী। if (x == -1) প্রথমে একটি পরীক্ষা করা দরকার।
chux - মনিকা পুনরায় ইনস্টল করুন

164

সেখানে হয় কিনা তা নির্ধারণ করতে একটি অপারেশন operands সবচেয়ে উল্লেখযোগ্য এক-বিট অবস্থান ও একটু মৌলিক বাইনারি-গণিত জ্ঞান ব্যবহার করে, ওভারফ্লো করার সম্ভাবনা রয়েছে একটি উপায়।

তদ্ব্যতীত, যে কোনও দুটি অপারেন্ডের ফলাফল (সর্বাধিক) বৃহত্তম অপারেন্ডারের সর্বোচ্চ এক বিটের চেয়ে কিছুটা বেশি। উদাহরণ স্বরূপ:

bool addition_is_safe(uint32_t a, uint32_t b) {
    size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
    return (a_bits<32 && b_bits<32);
}

গুণনের জন্য, যে কোনও দুটি অপারেটর অপারেন্ডগুলির বিটের যোগফল (সর্বাধিক) এর ফলাফল করবে। উদাহরণ স্বরূপ:

bool multiplication_is_safe(uint32_t a, uint32_t b) {
    size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
    return (a_bits+b_bits<=32);
}

একইভাবে, আপনি aএর bমতো পাওয়ারের ফলাফলের সর্বোচ্চ আকার অনুমান করতে পারেন :

bool exponentiation_is_safe(uint32_t a, uint32_t b) {
    size_t a_bits=highestOneBitPosition(a);
    return (a_bits*b<=32);
}

(অবশ্যই আপনার লক্ষ্য পূর্ণসংখ্যার জন্য বিটের সংখ্যাটি প্রতিস্থাপন করুন))

আমি সংখ্যায় সর্বোচ্চ এক-বিটের অবস্থান নির্ধারণের দ্রুততম উপায় সম্পর্কে নিশ্চিত নই, এখানে একটি নিষ্ঠুর শক্তি পদ্ধতি রয়েছে:

size_t highestOneBitPosition(uint32_t a) {
    size_t bits=0;
    while (a!=0) {
        ++bits;
        a>>=1;
    };
    return bits;
}

এটি নিখুঁত নয়, তবে এটি আপনাকে ভাল ধারণা দেবে আপনি অপারেশনটি করার আগে কোনও দুটি সংখ্যা উপচে পড়তে পারে কিনা। highestOneBitPositionফাংশনটির লুপের কারণে, আপনি যেভাবে প্রস্তাব করেছিলেন সেভাবে ফলাফলটি যাচাই করার চেয়ে দ্রুত হবে কিনা তা আমি জানি না , তবে এটি সম্ভবত (যদি আপনি জানেন যে অপারেশনগুলিতে আগে কত বিট ছিল)।


98
এবং অবশ্যই আপনি লগ ইন করতে সর্বোচ্চ ওবিটপজিশনের নাম পরিবর্তন করতে পারেন :)
অলিভার

37
হ্যাঁ, এটি একই ক্রিয়াকলাপ log2, তবে এটি গাণিতিক পটভূমি নেই এমন কারও পক্ষে অবশ্যই স্পষ্ট হবে না।
হেড গিক

48
এই অ্যালগরিদম নিরাপদ উত্তরগুলিকে অবমূল্যায়ন করে না? 2 ^ 31 + 0 সর্বোচ্চ ওয়ানবিটপজিশন (2 ^ 31) = 32 থেকে অনিরাপদ হিসাবে সনাক্ত করতে পারে 2 32. (2 ^ 32 - 1) * 1 32 + 1> 32 থেকে অনিরাপদ হিসাবে সনাক্ত করবে 1 1 * 100 থেকে 1 ^ 100 অনিরাপদ হিসাবে সনাক্ত করবে > 32.
Clahey

19
আপনার multiplication_is_safe 0x8000 * 0x10000ইচ্ছামত প্রবাহিত হবে (বিট পজিশনগুলি 16 + 17 = 33 যা > 32 ), যদিও এটি 0x8000 * 0x10000 = 0x80000000এখনও তা নয় কারণ এটি সম্ভবত এখনও স্বাক্ষরবিহীন 32 বিট ইন্টিতে ফিট করে। এটি মেয়ের উদাহরণগুলির মধ্যে একটি মাত্র যার জন্য এই কোডগুলি কাজ করে না। 0x8000 * 0x10001, ...
মিচি

13
@ জিT_ এমএইচ: আপনার বক্তব্য? আমি যেমন বলেছি, এটি নিখুঁত নয়; এটি একটি নিয়ম-অফ-থাম্ব নিশ্চিতভাবেই বলবে যে, যখন কিছু হয় নিরাপদ, কিন্তু কিনা তা নির্ধারণ করতে যে গণনা পূর্ণ হিসাব না করেই ঠিক হবে কোন উপায়। 0x8000 * 0x10000এই সংজ্ঞা অনুসারে "নিরাপদ" নয়, যদিও এটি ঠিক আছে কিনা।
হেড গিক

147

ঝাঁকুনি 3.4+ এবং জিসিসি 5+ পরীক্ষা করে গাণিতিক বিল্টিনগুলি সরবরাহ করে। তারা এই সমস্যার খুব দ্রুত সমাধান সরবরাহ করে, বিশেষত যখন বিট-পরীক্ষার সুরক্ষা চেকগুলির সাথে তুলনা করা হয়।

ওপির প্রশ্নের উদাহরণের জন্য, এটি এটির মতো কাজ করবে:

unsigned long b, c, c_test;
if (__builtin_umull_overflow(b, c, &c_test))
{
    // Returned non-zero: there has been an overflow
}
else
{
    // Return zero: there hasn't been an overflow
}

ক্ল্যাং ডকুমেন্টেশনে কোনও c_testওভারফ্লো দেখা গেলে ওভারফ্লোড ফলাফল রয়েছে কিনা তা নির্দিষ্ট করে না , তবে জিসিসি ডকুমেন্টেশন বলে যে এটি ঘটে। এই __builtinদু'জনেই সামঞ্জস্যপূর্ণ হতে পছন্দ করে, এটি সম্ভবত নিরাপদে ধরে নেওয়া নিরাপদ যে ক্ল্যাংও এভাবে কাজ করে।

নেই একটি __builtinপ্রতিটি গাণিতিক অপারেশন যে ওভারফ্লো পারেন (উপরন্তু, বিয়োগ, গুণ), স্বাক্ষর স্বাক্ষরবিহীন বিন্যাসের সাথে, int- আকারের, দীর্ঘ আয়তন, এবং দীর্ঘ দীর্ঘ মাপ জন্য জন্য। নামের বাক্য গঠনটি হ'ল __builtin_[us](operation)(l?l?)_overflow:

  • uজন্য স্বাক্ষরবিহীন বা sজন্য স্বাক্ষরিত ;
  • অপারেশন এক add, subবা mul;
  • কোন lপ্রত্যয় অর্থ অপারেশনগুলি হয় int; একটি lঅর্থ long; দুই lমানে long long

সুতরাং একটি পরীক্ষিত স্বাক্ষরিত দীর্ঘ পূর্ণসংখ্যার সংযোজনের জন্য এটি হবে __builtin_saddl_overflow। পুরো তালিকাটি ক্ল্যাং ডকুমেন্টেশন পৃষ্ঠায় পাওয়া যাবে ।

জিসিসি 5+ এবং ঝনঝন 3.8+ অতিরিক্ত মান ধরণ নির্দিষ্ট না করে যে কাজ জেনেরিক builtins অফার: __builtin_add_overflow, __builtin_sub_overflowএবং __builtin_mul_overflow। এগুলি এর চেয়ে ছোট প্রকারেও কাজ করে int

প্ল্যাটফর্মের জন্য সেরা যা বিল্টিনগুলি সবচেয়ে কম। X86-এ, তারা বহন করে, ওভারফ্লো করে এবং পতাকা সাইন করে।

ভিজ্যুয়াল স্টুডিওর cl.exe এর সরাসরি সমতুল্য নেই। স্বাক্ষরবিহীন সংযোজন এবং বিয়োগের জন্য, সহ <intrin.h>আপনাকে ব্যবহার করার অনুমতি দেবে addcarry_uNNএবং subborrow_uNN(যেখানে এনএন বিটের সংখ্যা, যেমন addcarry_u8বা subborrow_u64) or তাদের স্বাক্ষরটি কিছুটা অবসন্ন:

unsigned char _addcarry_u32(unsigned char c_in, unsigned int src1, unsigned int src2, unsigned int *sum);
unsigned char _subborrow_u32(unsigned char b_in, unsigned int src1, unsigned int src2, unsigned int *diff);

c_in/b_in ইনপুটতে বহন / ধার ধারনা এবং আউটপুট-এ ফেরতের মান হ'ল বহন / ধার। স্বাক্ষরিত ক্রিয়াকলাপ বা গুণনের জন্য এটি সমতুল্য বলে মনে হয় না।

অন্যথায়, উইন্ডোজের ঝাঁকুনি এখন উত্পাদন-প্রস্তুত (ক্রোমের পক্ষে যথেষ্ট ভাল), যাতে এটিও একটি বিকল্প হতে পারে।


__builtin_sub_overflowস্পষ্টভাবে কলঙ্ক 3.4 এ নেই।
রিচার্ড কুক

2
@ রিচার্ডকুক, এতে কিছুটা সময় লেগেছে তবে কলংয়ের সংস্করণ ৩.৯ অনুসারে জেনেরিক বিল্টিন রয়েছে।
26:36

@ টাম্ব্রে, আমি মনে করি না সেখানে আছে।
zneak

4
দস্তাবেজ অনুসারে , __builtin_add_overflowএবং বন্ধুরা ইতিমধ্যে ঝাঁকুনি 3.8 এ পাওয়া উচিত।
লেকেনস্টেইন

2
ধন্যবাদ। এটি দুর্দান্ত কাজ করে। ভিজ্যুয়াল সি ++ এর সাথে সম্পর্কিত ফাংশনটি কোন ধারণা? তাদের খুঁজে পাওয়া যাচ্ছে না।
মুদিত জৈন

53

কিছু সংকলক সিপিইউতে পূর্ণসংখ্যার ওভারফ্লো পতাকাটিতে অ্যাক্সেস সরবরাহ করে যা আপনি এর পরে পরীক্ষা করতে পারেন তবে এটি স্ট্যান্ডার্ড নয়।

আপনি গুণটি সম্পাদন করার আগে আপনি ওভারফ্লো সম্ভাবনার জন্যও পরীক্ষা করতে পারেন:

if ( b > ULONG_MAX / a ) // a * b would overflow

11
... অথবা সংখ্যাযুক্ত_লিট <TYPE> :: সর্বাধিক () ব্যবহার করুন
জোনাস গুললে

20
A = 0 - বিভাগ বিরতিতে তখন পরিচালনা করতে ভুলবেন না।
থেলিমা

16
@ থেলিমা: "a = 0" - এবং INT_MIN / -1 পরিচালনা করতে ভুলবেন না।
jww

1
তাহলে কি b == ULONG_MAX / a? তারপরে এটি এখনও মাপসই করা যায়, যা অবশিষ্টগুলি ছাড়াই aবিভক্ত হয় ULONG_MAX
সোয়াইন

মজার বিষয় হল, পারফরম্যান্সের ভিত্তিতে একটি বিভাগের তুলনায় একটি গুণটি দ্রুততর এবং আপনি প্রতিটি গুণনের জন্য একটি বিভাগ যুক্ত করছেন। এই মত না হয় সমাধান।
ড্রাম

40

সতর্কতা: জিসিসি সংকলনের সময় একটি ওভারফ্লো চেক অপ্টিমাইজ করতে পারে -O2। বিকল্পটি -Wallআপনাকে কিছু ক্ষেত্রে যেমন একটি সতর্কতা দেয়

if (a + b < a) { /* Deal with overflow */ }

তবে এই উদাহরণে নয়:

b = abs(a);
if (b < 0) { /* Deal with overflow */ }

একমাত্র নিরাপদ উপায় হ'ল ওভারফ্লো হওয়ার আগে এটি পরীক্ষা করা, যেমনটি সিইআরটি কাগজে বর্ণিত , এবং এটি পদ্ধতিগতভাবে ব্যবহার করা অবিশ্বাস্যরকম ক্লান্তিকর হবে।

সাথে -fwrapvসংকলন সমস্যা সমাধান করে, তবে কিছু অপ্টিমাইজেশন অক্ষম করে।

আমাদের মরিয়া হয়ে আরও ভাল সমাধান দরকার। আমি মনে করি যে সংযোজনকারীটি কোনও অপ্টিমাইজেশন তৈরি করার সময় ডিফল্টরূপে একটি সতর্কতা জারি করা উচিত যা ওভারফ্লো ঘটবে না তার উপর নির্ভর করে। বর্তমান পরিস্থিতি সংকলকটিকে একটি ওভারফ্লো চেক অপ্টিমাইজ করতে দেয়, যা আমার মতে অগ্রহণযোগ্য।


8
নোট করুন যে সংকলকরা কেবল স্বাক্ষরিত পূর্ণসংখ্যার প্রকারের সাহায্যে এটি করতে পারে ; স্বাক্ষরবিহীন পূর্ণসংখ্যার ধরণের জন্য ওভারফ্লো সম্পূর্ণরূপে সংজ্ঞায়িত। তবুও, হ্যাঁ, এটি বেশ বিপজ্জনক ফাঁদ!
SamB

1
"আমি মনে করি যে সংযোজনকারীটি কোনও অপ্টিমাইজেশন তৈরি করার সময় ডিফল্টরূপে একটি সতর্কতা জারি করা উচিত যা ওভারফ্লোটি ঘটবে না তার উপর নির্ভর করে" " - সুতরাং for(int k = 0; k < 5; k++) {...}একটি সতর্কতা বাড়াতে হবে?
ব্যবহারকারী 253751

2
@ মিম্বিস: এটি কেন করা উচিত? kসংকলনের সময় এর মানগুলি সহজেই নির্ধারণ করা যায়। সংকলকটি কোনও অনুমান করতে হবে না।
মাইক এমবি

2
@ এমমিবিস: উপরোক্ত উদ্ধৃতিগুলি: "আমি মনে করি যে
মাইক এমবি

1
@ মাইকএমবি অপ্টিমাইজেশন যেখানে সংস্থাপকটি nকেবলমাত্র নীচের 5 টি বিট ব্যবহার করে এমন একটি শিফ্ট নির্দেশ নির্গত করার আগে 32 এর চেয়ে কম কিনা তা পরীক্ষা করতে বিরক্ত করে না n?
ব্যবহারকারী 253751

30

কলং এখন স্বাক্ষরিত এবং স্বাক্ষরযুক্ত স্বাক্ষরিত উভয় পূর্ণসংখ্যার জন্য গতিশীল ওভারফ্লো চেকগুলিকে সমর্থন করে। দেখুন -fsanitize = পূর্ণসংখ্যা সুইচ। আপাতত, এটি ডিবাগের উদ্দেশ্যে সম্পূর্ণ সমর্থিত ডায়নামিক ওভারফ্লো চেকিং সহ একমাত্র সি ++ সংকলক।


25

আমি দেখতে পাচ্ছি যে প্রচুর লোক ওভারফ্লো সম্পর্কে প্রশ্নের উত্তর দিয়েছিল, তবে আমি তার মূল সমস্যাটি সমাধান করতে চেয়েছিলাম। তিনি বলেন, সমস্যা ছিল একটি খ খুঁজে পাওয়া = সি যে সমস্ত অঙ্কটি পুনরাবৃত্তি না করে ব্যবহার করা হয়। ঠিক আছে, তিনি এই পোস্টে যা চেয়েছিলেন তা নয়, তবে আমি এখনও মনে করি যে সমস্যার ওপরের সীমানা অধ্যয়ন করা এবং এই সিদ্ধান্তে পৌঁছানো দরকার ছিল যে তাকে কখনই একটি অতিরিক্ত প্রবাহ গণনা বা সনাক্ত করার দরকার পড়েনি (দ্রষ্টব্য: আমি দক্ষ নই গণিতে তাই আমি এই পদক্ষেপটি ধাপে ধাপে করেছিলাম, তবে শেষের ফলাফলটি এত সহজ ছিল যে এটির একটি সহজ সূত্র থাকতে পারে)।

মূল বিষয়টি হ'ল যে ওপরের সীমানাটি সমস্যাটি একটি, বি বা সি এর জন্য প্রয়োজন 98.765.432। যাইহোক, তুচ্ছ এবং অপ্রয়োজনীয় অংশগুলিতে সমস্যাটি বিভক্ত করে শুরু করুন:

  • x 0 == 1 (9, 8, 7, 6, 5, 4, 3, 2 এর সমস্ত অনুমতি সমাধান)
  • x 1 == x (কোনও সমাধান সম্ভব নয়)
  • 0 == 0 (কোনও সমাধান সম্ভব নয়)
  • 1 == 1 (কোনও সমাধান সম্ভব নয়)
  • বি , এ> ১, বি> ১ (তুচ্ছ নয়)

এখন আমাদের কেবল এটি দেখানো দরকার যে অন্য কোনও সমাধান সম্ভব নয় এবং কেবলমাত্র অনুমতিগুলি বৈধ হয় (এবং তারপরে তাদের মুদ্রণের কোডটি তুচ্ছ)। আমরা উপরের সীমানায় ফিরে যাই। আসলে উপরের সীমানা সি। 98.765.432। এটি উপরের সীমানা কারণ এটি 8 টি সংখ্যার (প্রতিটি এবং বি এর জন্য 10 সংখ্যার মোট বিয়োগ 1) সহ বৃহত্তম সংখ্যা। এই উপরের বাউন্ডটি কেবল গ এর জন্য কারণ খ এবং খ এর সীমানাগুলি খুব বেশি কম হওয়া উচিত কারণ তাত্পর্যপূর্ণ বৃদ্ধি, কারণ আমরা গণনা করতে পারি, খ 2 থেকে উপরের সীমানায় পৃথক:

    9938.08^2 == 98765432
    462.241^3 == 98765432
    99.6899^4 == 98765432
    39.7119^5 == 98765432
    21.4998^6 == 98765432
    13.8703^7 == 98765432
    9.98448^8 == 98765432
    7.73196^9 == 98765432
    6.30174^10 == 98765432
    5.33068^11 == 98765432
    4.63679^12 == 98765432
    4.12069^13 == 98765432
    3.72429^14 == 98765432
    3.41172^15 == 98765432
    3.15982^16 == 98765432
    2.95305^17 == 98765432
    2.78064^18 == 98765432
    2.63493^19 == 98765432
    2.51033^20 == 98765432
    2.40268^21 == 98765432
    2.30883^22 == 98765432
    2.22634^23 == 98765432
    2.15332^24 == 98765432
    2.08826^25 == 98765432
    2.02995^26 == 98765432
    1.97741^27 == 98765432

লক্ষ্য করুন, উদাহরণস্বরূপ শেষ লাইন: এটি বলে যে 1.97 ^ 27 ~ 98M। সুতরাং, উদাহরণস্বরূপ, 1 ^ 27 == 1 এবং 2 ^ 27 == 134.217.728 এবং এটি কোনও সমাধান নয় কারণ এটির 9 টি সংখ্যা রয়েছে (2> 1.97 সুতরাং এটি যা পরীক্ষা করা উচিত তার চেয়ে বড়)। এটি দেখা যায় যে, ক এবং খ পরীক্ষা করার জন্য উপলব্ধ সংমিশ্রণগুলি খুব ছোট। খ == ১৪ এর জন্য আমাদের ২ এবং ৩ চেষ্টা করে দেখতে হবে বি == 3 এর জন্য, আমরা ২ থেকে শুরু করে 462 এ থামি All সমস্ত ফলাফল ~ 98M এর চেয়ে কম হতে দেওয়া হয়েছে।

এখন কেবল উপরের সমস্ত সংমিশ্রণগুলি পরীক্ষা করুন এবং কোনও সংখ্যার পুনরাবৃত্তি না করে এমনগুলি সন্ধান করুন:

    ['0', '2', '4', '5', '6', '7', '8'] 84^2 = 7056
    ['1', '2', '3', '4', '5', '8', '9'] 59^2 = 3481
    ['0', '1', '2', '3', '4', '5', '8', '9'] 59^2 = 3481 (+leading zero)
    ['1', '2', '3', '5', '8'] 8^3 = 512
    ['0', '1', '2', '3', '5', '8'] 8^3 = 512 (+leading zero)
    ['1', '2', '4', '6'] 4^2 = 16
    ['0', '1', '2', '4', '6'] 4^2 = 16 (+leading zero)
    ['1', '2', '4', '6'] 2^4 = 16
    ['0', '1', '2', '4', '6'] 2^4 = 16 (+leading zero)
    ['1', '2', '8', '9'] 9^2 = 81
    ['0', '1', '2', '8', '9'] 9^2 = 81 (+leading zero)
    ['1', '3', '4', '8'] 3^4 = 81
    ['0', '1', '3', '4', '8'] 3^4 = 81 (+leading zero)
    ['2', '3', '6', '7', '9'] 3^6 = 729
    ['0', '2', '3', '6', '7', '9'] 3^6 = 729 (+leading zero)
    ['2', '3', '8'] 2^3 = 8
    ['0', '2', '3', '8'] 2^3 = 8 (+leading zero)
    ['2', '3', '9'] 3^2 = 9
    ['0', '2', '3', '9'] 3^2 = 9 (+leading zero)
    ['2', '4', '6', '8'] 8^2 = 64
    ['0', '2', '4', '6', '8'] 8^2 = 64 (+leading zero)
    ['2', '4', '7', '9'] 7^2 = 49
    ['0', '2', '4', '7', '9'] 7^2 = 49 (+leading zero)

এগুলির কোনওটিই সমস্যার সাথে মেলে না (এটি '0', '1', ..., '9' এর অনুপস্থিতিতেও দেখা যায়)।

উদাহরণ কোড যা এটি সমাধান করে। এছাড়াও লক্ষ করুন যে এটি পাইথনে লেখা হয়েছে, এটির জন্য নয় কারণ এটি স্বেচ্ছাচারিত নির্ভুলতা পূর্ণসংখ্যার প্রয়োজন (কোডটি 98 মিলিয়নের চেয়ে বড় কিছু গণনা করে না), তবে কারণ আমরা জানতে পেরেছি যে পরীক্ষার পরিমাণ এত কম যে আমাদের উচ্চ স্তরের ভাষা ব্যবহার করা উচিত এর অন্তর্নির্মিত পাত্রে এবং লাইব্রেরিগুলি ব্যবহার করুন (এছাড়াও দ্রষ্টব্য: কোডটিতে 28 টি লাইন রয়েছে)।

    import math

    m = 98765432
    l = []
    for i in xrange(2, 98765432):
        inv = 1.0/i
        r = m**inv
        if (r < 2.0): break
        top = int(math.floor(r))
        assert(top <= m)

        for j in xrange(2, top+1):
            s = str(i) + str(j) + str(j**i)
            l.append((sorted(s), i, j, j**i))
            assert(j**i <= m)

    l.sort()
    for s, i, j, ji in l:
        assert(ji <= m)
        ss = sorted(set(s))
        if s == ss:
            print '%s %d^%d = %d' % (s, i, j, ji)

        # Try with non significant zero somewhere
        s = ['0'] + s
        ss = sorted(set(s))
        if s == ss:
            print '%s %d^%d = %d (+leading zero)' % (s, i, j, ji)

1
আপনি কেন 9.876.543.210 উপরের সীমা হিসাবে ব্যবহার করছেন না?
টম রোগেরো

3
কারণ সমীকরণের বাম হাতের জন্য 2 ডিজিট অবশ্যই ব্যবহার করা উচিত।
hdante

2
এটি কোনও পার্থক্যের কারণ নয়, তবে উপরের সীমাটি 98765410 হিসাবে নেওয়া যেতে পারে যেমন আপনি এলএইচএসের মানগুলি> 1
পল চাইল্ডস

24

এখানে প্রশ্নের একটি "অ-বহনযোগ্য" সমাধান is ইন্টেল x86 এবং x64 সিপিইউগুলিতে তথাকথিত EFLAGS- রেজিস্টার রয়েছে , যা প্রতিটি পূর্ণসংখ্যার গাণিতিক ক্রিয়াকলাপের পরে প্রসেসর দ্বারা পূরণ করা হয়। আমি এখানে একটি বিশদ বিবরণ এড়িয়ে যাব। প্রাসঙ্গিক পতাকাগুলি হ'ল "ওভারফ্লো" পতাকা (মাস্ক 0x800) এবং "ক্যারি" পতাকা (মুখোশ 0x1)। তাদের সঠিকভাবে ব্যাখ্যা করতে, অপারেন্ডগুলি স্বাক্ষরিত বা স্বাক্ষরবিহীন প্রকারের কিনা তা বিবেচনা করা উচিত।

সি / সি ++ থেকে পতাকাগুলি পরীক্ষা করার জন্য এখানে ব্যবহারিক উপায় is নিম্নলিখিত কোডটি ভিজ্যুয়াল স্টুডিও 2005 বা আরও নতুন (32 এবং 64 বিট উভয়) পাশাপাশি জিএনইউ সি / সি ++ 64 বিটে কাজ করবে।

#include <cstddef>
#if defined( _MSC_VER )
#include <intrin.h>
#endif

inline size_t query_intel_x86_eflags(const size_t query_bit_mask)
{
    #if defined( _MSC_VER )

        return __readeflags() & query_bit_mask;

    #elif defined( __GNUC__ )
        // This code will work only on 64-bit GNU-C machines.
        // Tested and does NOT work with Intel C++ 10.1!
        size_t eflags;
        __asm__ __volatile__(
            "pushfq \n\t"
            "pop %%rax\n\t"
            "movq %%rax, %0\n\t"
            :"=r"(eflags)
            :
            :"%rax"
            );
        return eflags & query_bit_mask;

    #else

        #pragma message("No inline assembly will work with this compiler!")
            return 0;
    #endif
}

int main(int argc, char **argv)
{
    int x = 1000000000;
    int y = 20000;
    int z = x * y;
    int f = query_intel_x86_eflags(0x801);
    printf("%X\n", f);
}

অপারেশনগুলি যদি ওভারফ্লো ব্যতীত বহুগুণ হয় তবে আপনি 0 থেকে একটি রিটার্ন মান পাবেন query_intel_eflags(0x801), অর্থাত ক্যারি বা ওভারফ্লো পতাকা সেট করা নেই। মেইন () সরবরাহিত উদাহরণ কোডে, একটি ওভারফ্লো ঘটে এবং উভয় পতাকা 1 তে সেট করা থাকে check এই চেকটি আরও কোনও গণনা বোঝায় না, তাই এটি বেশ দ্রুত হওয়া উচিত।


21

যদি আপনার কাছে একটি ডেটাটাইপ থাকে যা আপনি পরীক্ষা করতে চান তার চেয়ে বড় (বলুন আপনি একটি 32-বিট যুক্ত করেছেন এবং আপনার একটি 64-বিট প্রকার রয়েছে) তবে এটি সনাক্ত করবে যে কোনও ওভারফ্লো হয়েছে কিনা। আমার উদাহরণটি একটি 8-বিট অ্যাডের জন্য। তবে এটি ছোট করে দেওয়া যায়।

uint8_t x, y;    /* Give these values */
const uint16_t data16    = x + y;
const bool carry        = (data16 > 0xFF);
const bool overflow     = ((~(x ^ y)) & (x ^ data16) & 0x80);

এটি এই পৃষ্ঠায় ব্যাখ্যা করা ধারণাগুলির উপর ভিত্তি করে: http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/Comb/overflow.html

একটি 32 বিট উদাহরণস্বরূপ, 0xFFহয়ে 0xFFFFFFFFএবং 0x80হয়ে 0x80000000এবং পরিশেষে uint16_tএকটি হয়েuint64_t

দ্রষ্টব্য : এটি পূর্ণসংখ্যার সংযোজন / বিয়োগফলকে ওভারফ্লো করে এবং আমি বুঝতে পেরেছি যে আপনার প্রশ্নটিতে গুণফল জড়িত। যে ক্ষেত্রে, বিভাগ সম্ভবত সেরা পদ্ধতির। এটি সাধারণত এমন এক উপায় যা callocবাস্তবায়নগুলি নিশ্চিত করে যে পরামিতিগুলি চূড়ান্ত আকার পেতে গুণিত হওয়ার সাথে সাথে সেগুলি উপচে পড়বে না।


লিঙ্কটি নষ্ট হয়েছে: HTTP 403: নিষিদ্ধ
পিটার মর্টেনসেন

18

সবচেয়ে সহজ উপায় হ'ল আপনার unsigned longগুলিকে unsigned long longএসগুলিতে রূপান্তর করা , আপনার গুণন করা এবং ফলাফলটিকে 0x100000000LL এর সাথে তুলনা করা।

আপনি সম্ভবত দেখতে পাবেন যে বিভাগটি করার চেয়ে এটি আপনার পক্ষে উদাহরণস্বরূপ আরও কার্যকর।

ওহ, এবং এটি সি এবং সি উভয় ক্ষেত্রেই কাজ করবে (যেমন আপনি উভয়ের সাথে প্রশ্ন ট্যাগ করেছেন)।


সবেমাত্র গ্লিব্যাক ম্যানুয়ালটি একবার দেখে নিচ্ছেন । এর FPE_INTOVF_TRAPঅংশ হিসাবে একটি পূর্ণসংখ্যার ওভারফ্লো ট্র্যাপ ( ) এর উল্লেখ রয়েছে SIGFPE। ম্যানুয়ালটিতে কদর্য বিট বাদে এটি আদর্শ হবে:

FPE_INTOVF_TRAP পূর্ণসংখ্যা ওভারফ্লো (যদি আপনি কোনও হার্ডওয়্যার-নির্দিষ্ট ফ্যাশনে ওভারফ্লো ট্র্যাপিং সক্ষম না করেন তবে একটি সি প্রোগ্রামে অসম্ভব)।

সত্যিই কিছুটা লজ্জা লাগছে।


4
হি ... আমি যা বলিনি তা হ'ল আমি বৃহত্তর সংখ্যা নিয়ে একটি সমস্যা সমাধানের জন্য একটি প্রোগ্রাম লেখার প্রস্তুতির জন্য এই প্রশ্নটি জিজ্ঞাসা করছি, যার মধ্যে আমি ইতিমধ্যে দীর্ঘ দীর্ঘ ব্যবহার করছি। যেহেতু দীর্ঘতর দীর্ঘসূত্রটি সি ++ স্ট্যান্ডার্ডে নেই (অভিযোগে), তাই আমি বিভ্রান্তি এড়াতে 32-বিট সংস্করণটি দিয়ে আটকেছি।
ক্রিস জনসন

আমি ব্যবহার পরামর্শ দিতে চাই ULONG_MAXকোন ধরনের করা আরো সহজ ও কঠোর-কোডিং চেয়ে বেশি পোর্টেবল 0x100000000
jw013

24
এই কাজ যখন নেই longএবং long longএকই আকারের (যেমন অনেক 64-বিট কম্পাইলার দিকে) হয়।
ইন্টারজয়

ওভারফ্লো সম্পর্কে আপনাকে বলতে সংকেতের উপর নির্ভর করা যাইহোক সত্যিই ধীর হবে।
স্যামবি

@ স্যামবি কেবলমাত্র যদি ওভারফ্লোগুলি ঘন ঘন আশা করা হত।
ব্যবহারকারী 253751

17

কমপক্ষে সংযোজনগুলির জন্য ওভারফ্লো সনাক্ত করার জন্য এখানে একটি সত্যই দ্রুত উপায়, যা গুণ, বিভাগ এবং পাওয়ার-এর জন্য নেতৃত্ব দিতে পারে।

ধারণাটি হ'ল ঠিক কারণ প্রসেসরটি কেবল মান মোড়কে শূন্যে ফিরে যেতে দেয় এবং সি / সি ++ নির্দিষ্ট কোনও প্রসেসর থেকে বিমূর্ত করতে পারে, আপনি করতে পারেন:

uint32_t x, y;
uint32_t value = x + y;
bool overflow = value < (x | y);

এটি উভয়ই নিশ্চিত করে যে যদি একটি অপারেন্ড শূন্য হয় এবং একটি না হয় তবে ওভারফ্লোটি ভুলভাবে সনাক্ত করা যায় না এবং পূর্বের পরামর্শ অনুসারে প্রচুর নং / এক্সওআর / ওআর / পরীক্ষার ক্রিয়াকলাপের চেয়ে উল্লেখযোগ্যভাবে দ্রুত হয়।

হিসাবে চিহ্নিত হয়েছে, এই পদ্ধতির, যদিও আরও অন্যান্য বিস্তৃত উপায় চেয়ে ভাল, এখনও আশাবাদী। নিম্নলিখিতটি অপ্টিমাইজেশান সহ মূল কোডটির একটি সংশোধন করেছে:

uint32_t x, y;
uint32_t value = x + y;
const bool overflow = value < x; // Alternatively "value < y" should also work

গুণনের ওভারফ্লো সনাক্ত করার জন্য আরও কার্যকর এবং সস্তা উপায় হ'ল:

uint32_t x, y;
const bool overflow = (x >> 16U) * (y >> 16U);
uint32_t value = overflow ? UINT32_MAX : x * y;

এটি ওভারফ্লোতে UINT32_MAX এর ফলস্বরূপ, বা গুণনের ফলাফল। এক্ষেত্রে স্বাক্ষরিত পূর্ণসংখ্যার জন্য গুণটির অগ্রযাত্রার অনুমতি দেওয়া কঠোরভাবে অপরিবর্তিত আচরণ।


গণনা তত্ত্বের কারণে আমি দ্বিমত পোষণ করছি .. নিম্নলিখিতটি বিবেচনা করুন: y> এক্স, মান ওভারফ্লো ওভারফ্লোতে = মিথ্যা - অতএব যৌক্তিক ব্যবহার বা এই ভাঙ্গা আচরণ রোধ করতে ..
DX-MON

পরীক্ষাটি আপনার দেওয়া সংখ্যার জন্য কাজ করে (x: = 1, y: = 255, আকার = uint8_t): মান 0 (1 + 255) হবে এবং 0 <1 সত্য। এটি প্রতিটি সংখ্যক জুটির পক্ষে কাজ করে।
গুন্থার পাইজ

হুম, আপনি ভাল কথা বলছেন। আমি এখনও ট্রিক বা ট্রিক ব্যবহার করে সুরক্ষার পাশে আছি যদিও কোনও ভাল সংকলক হিসাবে এটি সরবরাহকারীকে অনুকূল করে তুলবে আপনি "0 + 4" এর মতো অপ্রবাহিত সংখ্যাসমূহ সহ সমস্ত ইনপুটগুলির পক্ষে সত্যই সঠিক যেখানে ফলাফলটি ওভারফ্লো হবে না।
DX-MON

4
যদি একটি ওভারফ্লো, চেয়ে x+y>=256এবং value=x+y-256। কারণ y<256সর্বদা সত্য, (y-256) negativeণাত্মক এবং তাই value < xসর্বদা সত্য। প্রবাহিত নয় এমন মামলার প্রমাণও একই রকম।
গুঁথার পাইজ

2
@ ডিএক্স-মন: আপনার যদি পূর্ববর্তী অ্যাড থেকে ক্যারি বিট থাকে তবে আপনার প্রথম পদ্ধতিটি প্রয়োজনীয়। uint32_t x[N], y[N], z[N], carry=0; for (int i = 0; i < N; i++) { z[i] = x[i] + y[i] + carry; carry = z[i] < (x[i] | y[i]); }আপনি যদি orমানগুলি না মানেন তবে আপনি একটি অপরেন্ড এবং ক্যারি বিট শূন্য এবং একটি অপারেন্ড সত্তা 0xffffffffএবং বহনকারী বিট একর মধ্যে পার্থক্য করতে সক্ষম হবেন না ।
ম্যাট

14

আপনি সি / সি ++ থেকে ওভারফ্লো পতাকাটি অ্যাক্সেস করতে পারবেন না।

কিছু সংকলক আপনাকে কোডে ফাঁদ নির্দেশাবলী সন্নিবেশ করার অনুমতি দেয়। জিসিসিতে বিকল্পটি -ftrapv

আপনি কেবলমাত্র পোর্টেবল এবং সংকলক স্বাধীন জিনিসটি করতে পারেন তা হ'ল নিজে থেকে ওভারফ্লো পরীক্ষা করা। যেমন আপনি আপনার উদাহরণে করেছেন।

তবে, -ftrapvসর্বশেষতম জিসিসি ব্যবহার করে x86-এ কিছুই করার জন্য মনে হচ্ছে না। আমার ধারণা এটি কোনও পুরানো সংস্করণ থেকে বা অন্য কোনও আর্কিটেকচারের সাথে নির্দিষ্ট from আমি সংযোজকটি প্রতিটি সংযোজনের পরে একটি INTO অপকোড toোকানোর প্রত্যাশা করেছিল। দুর্ভাগ্যক্রমে এটি এটি করে না।


সম্ভবত এটি পরিবর্তিত হয়: -ফ্রাটপভি সাইগউইন বাক্সে জিসিসি ৪.৩.৪ ব্যবহার করে দুর্দান্ত কাজ করে বলে মনে হচ্ছে। স্ট্যাকওভারফ্লো
নাট কোহল

3
আপনারা দুজনেই ঠিক বলেছেন। -ফুটপাভি কাজটি করে তবে কেবল স্বাক্ষরিত পূর্ণসংখ্যার জন্য
জ্যাব

14

স্বাক্ষরবিহীন পূর্ণসংখ্যার জন্য, পরীক্ষা করে দেখুন যে আর্গুমেন্টগুলির মধ্যে একটির চেয়ে ছোট:

unsigned int r, a, b;
r = a + b;
if (r < a)
{
    // Overflow
}

স্বাক্ষরিত পূর্ণসংখ্যার জন্য আপনি আর্গুমেন্টের চিহ্ন এবং ফলাফলের চিহ্ন পরীক্ষা করতে পারেন।

বিভিন্ন চিহ্নের পূর্ণসংখ্যাগুলি উপচে পড়তে পারে না এবং একই চিহ্নের পূর্ণসংখ্যা কেবল ওভারফ্লো হয়ে যায় যদি ফলাফলটি ভিন্ন চিহ্নের হয়:

signed int r, a, b, s;
r = a + b;
s = a>=0;
if (s == (b>=0) && s != (r>=0))
{
    // Overflow
}

ঠিক আছে প্রথম পদ্ধতিটি স্বাক্ষরিত পূর্ণসংখ্যার জন্যও কাজ করবে, তাই না? char result = (char)127 + (char)3;-126 হবে; উভয় অপারেন্ডের চেয়ে ছোট।
primfaktor

1
ওহ আমি দেখতে পাচ্ছি, সমস্যাটি হ'ল স্বাক্ষরিত ধরণের জন্য এটি অপরিজ্ঞাত।
primfaktor

27
-1 স্বাক্ষরযুক্ত সংখ্যার ওভারফ্লো অনির্ধারিত আচরণের ফলাফল দেয় (সুতরাং পরীক্ষাটি আসলে কার্যকর হতে দেরি হয়ে গেছে)।
ভু

1
@ প্রাইমফ্যাক্টর এটি স্বাক্ষরিত int- এর জন্য কাজ করে না: চর ((- 127) + (-17)) = 112. স্বাক্ষরিত int এর জন্য আপনাকে অবশ্যই যুক্তি এবং ফলাফলের সাইন বিটটি পরীক্ষা করতে হবে
ফুক্লভ

3
ইতিমধ্যে বলা হয়েছে যে, ওভারফ্লো ক্ষেত্রে A + b এর অপরিজ্ঞাত আচরণের কারণে স্বাক্ষরিত পূর্ণসংখ্যার সমাধান কাজ করে না। অপারেশন করার পূর্বে স্বাক্ষরিত পূর্ণসংখ্যার সাথে ওভারফ্লো পরীক্ষা করা উচিত
মারওয়ান বুরেলে

11

ভাসমান পয়েন্ট সংখ্যাগুলির জন্য আমার এই একই প্রশ্নের উত্তর দেওয়া দরকার ছিল, যেখানে বিট মাস্কিং এবং শিফটিংটি আশাব্যঞ্জক বলে মনে হচ্ছে না। স্বাক্ষরিত এবং স্বাক্ষরবিহীন, পূর্ণসংখ্যা এবং ভাসমান পয়েন্ট সংখ্যাগুলির জন্য আমি যে পদ্ধতির সমাধান করেছি। মধ্যবর্তী গণনার জন্য প্রচার করার জন্য আরও বড় কোনও ডেটা টাইপ না থাকলেও এটি কাজ করে। এটি এই সমস্ত ধরণের জন্য সর্বাধিক দক্ষ নয়, তবে এটি তাদের সকলের জন্য কাজ করে, এটি ব্যবহারের পক্ষে মূল্যবান।

স্বাক্ষরিত ওভারফ্লো পরীক্ষা, সংযোজন এবং বিয়োগফল:

  1. ধ্রুবকগুলি পান যা MAXVALUE এবং MINVALUE প্রকারের জন্য বৃহত্তম এবং ক্ষুদ্রতম সম্ভাব্য মানের প্রতিনিধিত্ব করে।

  2. অপারেশনগুলির লক্ষণগুলি গণনা করুন এবং তুলনা করুন।

    ক। উভয়ই মান যদি শূন্য হয়, তবে সংযোজন বা বিয়োগফল উভয়ই উপচে পড়তে পারে না। অবশিষ্ট পরীক্ষা ছেড়ে যান।

    খ। যদি লক্ষণগুলি বিপরীত হয় তবে সংযোজন উপচে পড়তে পারে না। অবশিষ্ট পরীক্ষা ছেড়ে যান।

    গ। যদি লক্ষণগুলি একই হয়, তবে বিয়োগটি ওভারফ্লো হতে পারে না। অবশিষ্ট পরীক্ষা ছেড়ে যান।

  3. MAXVALUE এর ইতিবাচক ওভারফ্লো জন্য পরীক্ষা Test

    ক। উভয় লক্ষণ যদি ইতিবাচক হয় এবং MAXVALUE - A <B হয়, তবে সংযোজন উপচে পড়বে।

    খ। যদি বি এর চিহ্নটি নেতিবাচক হয় এবং MAXVALUE - A <-B হয়, তবে বিয়োগফল উপচে পড়বে।

  4. MINVALUE এর নেতিবাচক ওভারফ্লো জন্য পরীক্ষা Test

    ক। যদি উভয় চিহ্নই নেতিবাচক এবং MINVALUE - A> B হয় তবে সংযোজন উপচে পড়বে।

    খ। যদি A এর চিহ্নটি negativeণাত্মক এবং MINVALUE - A> B হয় তবে বিয়োগফল উপচে পড়বে।

  5. অন্যথায়, কোন ওভারফ্লো।

ওভারফ্লো পরীক্ষা, গুণ এবং বিভাগে স্বাক্ষরিত:

  1. ধ্রুবকগুলি পান যা MAXVALUE এবং MINVALUE প্রকারের জন্য বৃহত্তম এবং ক্ষুদ্রতম সম্ভাব্য মানের প্রতিনিধিত্ব করে।

  2. অপারেশনগুলির দৈর্ঘ্যের (পরম মান) একের সাথে তুলনা করুন এবং তুলনা করুন। (নীচে, ধরে নিন যে এ এবং বি এই স্বীকৃতি, স্বাক্ষরিত মূল নয়))

    ক। উভয়ই মান যদি শূন্য হয়, তবে গুণগুলি উপচে পড়তে পারে না এবং বিভাগটি শূন্য বা অসীমতা অর্জন করে।

    খ। উভয়ই মান যদি এক হয় তবে গুণ এবং বিভাগটি ওভারফ্লো করতে পারে না।

    গ। যদি কোনও অপরেন্দ্রের দৈর্ঘ্য একের নীচে থাকে এবং অন্যটির অপরটির পরিমাণ একের চেয়ে বেশি হয়, তবে গুণগুলি উপচে পড়তে পারে না।

    ঘ। যদি দৈর্ঘ্য উভয়ই একের কম হয় তবে বিভাগটি উপচে পড়তে পারে না।

  3. MAXVALUE এর ইতিবাচক ওভারফ্লো জন্য পরীক্ষা Test

    ক। উভয় অপারেন্ড যদি একের বেশি এবং MAXVALUE / A <B হয় তবে গুণটি ওভারফ্লো হবে।

    খ। বি যদি একের কম হয় এবং MAXVALUE * B <A হয় তবে বিভাগটি উপচে পড়বে।

  4. অন্যথায়, কোন ওভারফ্লো।

দ্রষ্টব্য: MINVALUE ন্যূনতম ওভারফ্লো 3 দ্বারা পরিচালিত হয়, কারণ আমরা নিখুঁত মান নিয়েছি। তবে, যদি ABS (MINVALUE)> MAXVALUE হয়, তবে আমাদের কিছু বিরল মিথ্যা ধনাত্মক হবে।

আন্ডারফ্লোর জন্য পরীক্ষাগুলি সমান, তবে ইপিএসলন (শূন্যের চেয়ে ক্ষুদ্রতম ধনাত্মক সংখ্যা) জড়িত।


1
কমপক্ষে POSIX সিস্টেমে, SIGFPE সিগন্যালটি ভাসমান পয়েন্টের জন্য / ওভারফ্লোগুলির জন্য সক্ষম করা যায়।
ক্রিস জনসন

ফ্লোটিং পয়েন্ট এবং ব্যাক ওয়ার্কে রূপান্তর করার সময়, এটি অন্যান্য সমাধানের চেয়ে ধীর গতিতে (32 বিবিটি মেশিনে আমার পরীক্ষা অনুযায়ী)।
জানকানিস

একটি পর্যালোচক 2 বিয়োগ বিয়োগের জন্য একটি অনুপস্থিত কেস সনাক্ত করেছেন I আমি সম্মত হই যে 0 - MINVALUE উপচে পড়বে। সুতরাং এই ক্ষেত্রে জন্য পরীক্ষা যোগ করা উচিত।
পল চেরনোচ

<পেডেন্টিক> পূর্ণসংখ্যাগুলি পাতাল থেকে প্রবাহিত হয় না (= কোনও নির্ভুলতার সাথে প্রতিনিধিত্ব করতে শূন্যের খুব কাছাকাছি হয়ে যায়)। 1.0e-200 / 1.0e200আইইইই ডাবলস ধরে ধরে একটি প্রকৃত ভূগর্ভের উদাহরণ হবে। পরিবর্তে এখানে সঠিক শব্দটি নেতিবাচক ওভারফ্লো is </ translation>
আর্ন ভোগেল

সুনির্দিষ্টভাবে বলতে গেলে, পূর্ণসংখ্যাগুলি কেন ডুবো প্রবাহ হিসাবে বিবেচিত হবে না কারণ সংজ্ঞায়িত কাটছাঁটি আচরণ, উদাহরণস্বরূপ 1/INT_MAXভাল আন্ডারফ্লো হিসাবে বিবেচনা করা যেতে পারে, তবে ভাষা কেবল কাটা শূন্যকে আদেশ করে।
আর্ন ভোগেল

8

সিইআরটি স্বাক্ষরিত পূর্ণসংখ্যার ওভারফ্লো, স্বাক্ষরবিহীন পূর্ণসংখ্যার মোড়ক, এবং ইনফিটিলিটি রেঞ্জ (এআইআর) পূর্ণসংখ্যার মডেল ব্যবহার করে পূর্ণসংখ্যার কাটা সনাক্তকরণ এবং রিপোর্ট করার জন্য একটি নতুন পদ্ধতির বিকাশ করেছে। সিইআরটি মডেলটি বর্ণনা করে একটি প্রযুক্তিগত প্রতিবেদন প্রকাশ করেছে এবং জিসিসি ৪.৪.০ এবং জিসিসি ৪.৪.০ ভিত্তিতে একটি ওয়ার্কিং প্রোটোটাইপ তৈরি করেছে।

এআইআর পূর্ণসংখ্যার মডেলটি হয় একটির সমতুল্য একটি মান উত্পাদন করে যা অসীম রেঞ্জযুক্ত পূর্ণসংখ্যা ব্যবহার করে বা রানটাইম সীমাবদ্ধতা লঙ্ঘনের ফলে প্রাপ্ত হত। পূর্বের পূর্ণসংখ্যার মডেলগুলির বিপরীতে, এআইআর পূর্ণসংখ্যার জন্য সুনির্দিষ্ট ফাঁদগুলির প্রয়োজন হয় না এবং ফলস্বরূপ বেশিরভাগ বিদ্যমান অপটিমাইজেশনগুলি ভেঙে বা বাধা দেয় না।


আমি লিঙ্কটিতে দরকারী কিছু দেখতে পাইনি, তবে এটি এমন একটি মডেলের মতো যা আমি দীর্ঘকাল ধরে সমর্থন করেছি। এটি বেশিরভাগ কার্যকর অপ্টিমাইজেশান সমর্থন করে, পাশাপাশি কার্যকর শব্দার্থ গ্যারান্টি সমর্থন করে যে বেশিরভাগ বাস্তবায়ন মূলত কোনও চার্জ দিতে পারে না। কোড যদি জানে যে আউটপুট সম্পর্কিত সমস্ত ক্ষেত্রে কোনও ফাংশনের ইনপুটগুলি বৈধ হবে , তবে আউটপুটটি গুরুত্বপূর্ণ হবে কিনা তা আগাম জানে না, যেখানে কোনও কিছুই প্রভাব ফেলবে না সে ক্ষেত্রে ওভারফ্লোগুলি ঘটতে দিতে সক্ষম হচ্ছে এগুলি যে কোনও মূল্যে প্রতিরোধ করার চেয়ে সহজ এবং আরও কার্যকর।
ক্যাট

8

আর একটি আকর্ষণীয় সরঞ্জাম হ'ল আইওসি: সি / সি ++ এর জন্য একটি পূর্ণসংখ্যার ওভারফ্লো চেকার

এটি একটি প্যাচযুক্ত কলং সংকলক, যা সংকলনের সময় কোডটিতে চেক যুক্ত করে।

আপনি আউটপুট এর মতো দেখতে পাবেন:

CLANG ARITHMETIC UNDEFINED at <add.c, (9:11)> :
Op: +, Reason : Signed Addition Overflow,
BINARY OPERATION: left (int32): 2147483647 right (int32): 1

1
এই প্যাচটি এখন অন্যান্য স্যানিটাইজারদের মধ্যে ঝনঝন কোডবেজে একীভূত হয়েছে, আমার উত্তর দেখুন।
জ্যাব

7

সমাবেশ ভাষা ব্যবহার করে একটি সমাধানের আরও একটি রূপ একটি বাহ্যিক পদ্ধতি। লিনাক্স x64 এর অধীনে g ++ এবং ফাস্ট ব্যবহার করে স্বাক্ষরযুক্ত পূর্ণসংখ্যা গুণনের জন্য এই উদাহরণ।

এই পদ্ধতিটি দুটি স্বাক্ষরযুক্ত পূর্ণসংখ্যার আর্গুমেন্ট (32 বিট) ( এমডি 64 এর স্পেসিফিকেশন অনুযায়ী (বিভাগ 3.2.3 প্যারামিটার পাসিং ) গুন করে ।

ক্লাসটি যদি ইন্টিগের হয় তবে% rdi,% rsi,% rdx,% rcx,% r8, এবং% r9 এর পরবর্তী উপলব্ধ নিবন্ধ ব্যবহার করা হবে

(আমার কোডে এডি এবং এএসসি রেজিস্ট্রেশন করা হয়)) এবং যদি কোনও ওভারফ্লো হয়েছে তবে ফলাফলটি বা 0 প্রদান করে।

format ELF64

section '.text' executable

public u_mul

u_mul:
  MOV eax, edi
  mul esi
  jnc u_mul_ret
  xor eax, eax
u_mul_ret:
ret

টেস্ট:

extern "C" unsigned int u_mul(const unsigned int a, const unsigned int b);

int main() {
    printf("%u\n", u_mul(4000000000,2)); // 0
    printf("%u\n", u_mul(UINT_MAX/2,2)); // OK
    return 0;
}

Asm অবজেক্ট ফাইলের সাথে প্রোগ্রামটি লিঙ্ক করুন। আমার ক্ষেত্রে, কিউটি ক্রিয়েটারে , এটি LIBSএকটি .pro ফাইলে যুক্ত করুন।


5

দ্বিগুণ সহ ফলাফল গণনা করুন। তাদের 15 টি উল্লেখযোগ্য সংখ্যা রয়েছে। আপনার প্রয়োজনীয়তার 10 8 এর সি তে কঠোর উপরের আবদ্ধ রয়েছে  - এটিতে সর্বোচ্চ 8 টি সংখ্যা থাকতে পারে have সুতরাং, ফলাফলটি পরিসীমাতে থাকলে সুনির্দিষ্ট হবে এবং এটি অন্যথায় উপচে পড়বে না।


5

32-বিট মেশিনের ওভারফ্লো বিটটি পরীক্ষা করার জন্য এই ম্যাক্রোটি ব্যবহার করে দেখুন (অ্যাঞ্জেল সিনিগারস্কির সমাধানটি অভিযোজিত)

#define overflowflag(isOverflow){   \
size_t eflags;                      \
asm ("pushfl ;"                     \
     "pop %%eax"                    \
    : "=a" (eflags));               \
isOverflow = (eflags >> 11) & 1;}

আমি এটিকে ম্যাক্রো হিসাবে সংজ্ঞায়িত করেছি কারণ অন্যথায় ওভারফ্লো বিটটি ওভাররাইট করা হত।

তারপরে উপরের কোড সেজমেন্টের সাথে সামান্য প্রয়োগ রয়েছে:

#include <cstddef>
#include <stdio.h>
#include <iostream>
#include <conio.h>
#if defined( _MSC_VER )
#include <intrin.h>
#include <oskit/x86>
#endif

using namespace std;

#define detectOverflow(isOverflow){     \
size_t eflags;                      \
asm ("pushfl ;"                     \
    "pop %%eax"                     \
    : "=a" (eflags));               \
isOverflow = (eflags >> 11) & 1;}

int main(int argc, char **argv) {

    bool endTest = false;
    bool isOverflow;

    do {
        cout << "Enter two intergers" << endl;
        int x = 0;
        int y = 0;
        cin.clear();
        cin >> x >> y;
        int z = x * y;
        detectOverflow(isOverflow)
        printf("\nThe result is: %d", z);
        if (!isOverflow) {
            std::cout << ": no overflow occured\n" << std::endl;
        } else {
            std::cout << ": overflow occured\n" << std::endl;
        }

        z = x * x * y;
        detectOverflow(isOverflow)
        printf("\nThe result is: %d", z);
        if (!isOverflow) {
            std::cout << ": no overflow ocurred\n" << std::endl;
        } else {
            std::cout << ": overflow occured\n" << std::endl;
        }

        cout << "Do you want to stop? (Enter \"y\" or \"Y)" << endl;

        char c = 0;

        do {
            c = getchar();
        } while ((c == '\n') && (c != EOF));

        if (c == 'y' || c == 'Y') {
            endTest = true;
        }

        do {
            c = getchar();
        } while ((c != '\n') && (c != EOF));

    } while (!endTest);
}

4
সমস্ত 32-বিট মেশিনগুলি ইন্টেল x86- সামঞ্জস্যপূর্ণ নয়, এবং সমস্ত সংকলকগুলি gnu এসেম্বলির সিনট্যাক্সকে সমর্থন করে না ( _MSC_VERএমএস কম্পাইলগুলি সমস্ত কোড প্রত্যাখ্যান করবে এমনটি পরীক্ষা করে আপনি কোড পোস্ট করেন তা মজার বিষয় বলে মনে হয় )।
বেন ভয়েগট

2

সি-তে ইন্টিজার ওভারফ্লোগুলি ক্যাচিং সিআরটি দ্বারা আলোচিত (সাধারণভাবে পরিচালিত ধরণের ক্ষেত্রে এটি আরও সাধারণ) এর চেয়ে বেশি সাধারণ সমাধান সমাধান করে, যদিও এটির জন্য কিছু জিসিসি এক্সটেনশন প্রয়োজন (তারা জানি না যে তারা কতটা ব্যাপকভাবে সমর্থিত)।


2

আপনি সি / সি ++ থেকে ওভারফ্লো পতাকাটি অ্যাক্সেস করতে পারবেন না।

আমি এর সাথে একমত নই আপনি কিছু ইনলাইন সমাবেশ ভাষা লিখতে এবং ব্যবহার করতে পারেনjo ওভারফ্লো আটকে দেওয়ার জন্য আপনি x86 এ আছেন ধরে ধরে (ওভারফ্লো) ঝাঁপিয়ে ruction অবশ্যই, আপনার কোডটি আর স্থাপত্যের জন্য পোর্টেবল হবে না।

তাকান info asএবং info gcc


8
ইনলাইন অ্যাসেমব্লার কোনও সি / সি ++ বৈশিষ্ট্য এবং প্ল্যাটফর্মটি স্বতন্ত্র নয়। X86-এ আপনি বিটিডাব্লু শাখার ইনস্ট্রাকশন আইস্টিড ব্যবহার করতে পারেন।
নিলস পিপেনব্রিংক

0

হেড গিকের উত্তরে প্রসারিত করার জন্য, আরও দ্রুত করার উপায় আছে addition_is_safe;

bool addition_is_safe(unsigned int a, unsigned int b)
{
    unsigned int L_Mask = std::numeric_limits<unsigned int>::max();
    L_Mask >>= 1;
    L_Mask = ~L_Mask;

    a &= L_Mask;
    b &= L_Mask;

    return ( a == 0 || b == 0 );
}

এটি মেশিন-আর্কিটেকচারকে নিরাপদ ব্যবহার করে, সেই -৪-বিট এবং 32-বিট স্বাক্ষরবিহীন পূর্ণসংখ্যাগুলি এখনও ঠিক কাজ করবে। মূলত, আমি একটি মুখোশ তৈরি করি যা সর্বাধিক তাৎপর্যপূর্ণ বিট ব্যতীত অন্য সবকেই মাস্ক করে দেয়। তারপরে, আমি উভয় পূর্ণসংখ্যার মুখোশ পরেছি এবং যদি তাদের উভয়ের মধ্যেও এই বিট সেট না থাকে তবে সংযোজনটি নিরাপদ।

আপনি যদি কোনও নির্মাণকারীর মুখোশ প্রাক-আরম্ভ করেন তবে এটি আরও দ্রুত হবে, যেহেতু এটি কখনই পরিবর্তন হয় না।


5
এটি সঠিক নয়। ক্যারি নিম্ন অবস্থান থেকে বিট আনতে পারে যা ওভারফ্লো হতে পারে। যোগ বিবেচনা করুন UINT_MAX + 1। মাস্কিংয়ের পরে, aউচ্চ বিট সেট থাকবে, তবে 1শূন্য হয়ে যাবে এবং তাই ফাংশনটি ফিরে আসবে true, সংযোজন নিরাপদ - তবুও আপনি সরাসরি ওভারফ্লোতে যাচ্ছেন।
সোয়াইন

0

mozilla::CheckedInt<T>পূর্ণসংখ্যার প্রকারের জন্য ওভারফ্লো-চেক করা পূর্ণসংখ্যার গণিত সরবরাহ Tকরে (ক্ল্যাং এবং জিসিসি তে উপলব্ধ হিসাবে সংকলক অন্তর্ভুক্তি ব্যবহার করে)। কোড MPL 2.0 বয়সী তিন উপর নির্ভর করে ( IntegerTypeTraits.h, Attributes.hএবং Compiler.h) অন্য হেডার শুধুমাত্র অ-মানক গ্রন্থাগার হেডার প্লাস মোজিলা-নির্দিষ্ট কথন যন্ত্রপাতি । আপনি যদি কোডটি আমদানি করেন তবে আপনি সম্ভবত দৃ machinery় সংস্থানটি পরিবর্তন করতে চান।


-1

এমসাল্টারের উত্তর একটি ভাল ধারণা।

যদি পূর্ণসংখ্যার গণনা প্রয়োজন হয় (নির্ভুলতার জন্য) তবে ভাসমান পয়েন্ট পাওয়া যায় তবে আপনি এর মতো কিছু করতে পারেন:

uint64_t foo(uint64_t a, uint64_t b) {
    double dc;

    dc = pow(a, b);

    if (dc < UINT_MAX) {
       return (powu64(a, b));
    }
    else {
      // Overflow
    }
}

সাধারণত, আমি বলব যে ভাসমান পয়েন্টে গণনা পুনরাবৃত্তি করা একটি খারাপ ধারণা, তবে ক্ষুদ্রাকৃতির এই নির্দিষ্ট ক্ষেত্রে একটি ^ সি, এটি আরও কার্যকর হতে পারে। তবে পরীক্ষাটি হওয়া উচিত (c * log(a) < max_log), কোথায়const double max_log = log(UINT_MAX)
টবি স্পিড 9

-1

X86 নির্দেশিকা সেটটিতে একটি স্বাক্ষরবিহীন বহুগুণ নির্দেশ অন্তর্ভুক্ত যা ফলাফল দুটি রেজিস্টারে সংরক্ষণ করে। সি থেকে সেই নির্দেশটি ব্যবহার করতে, একটি 64৪-বিট প্রোগ্রামে (জিসিসি) নিম্নলিখিত কোডটি লিখতে পারে:

unsigned long checked_imul(unsigned long a, unsigned long b) {
  unsigned __int128 res = (unsigned __int128)a * b;
  if ((unsigned long)(res >> 64))
    printf("overflow in integer multiply");
  return (unsigned long)res;
}

একটি 32-বিট প্রোগ্রামের জন্য, ফলাফলটি 64 বিট এবং পরামিতিগুলি 32 বিট করা দরকার।

একটি বিকল্প হ'ল পতাকা নিবন্ধন পরীক্ষা করার জন্য সংকলক-নির্ভর অন্তর্নিহিত ব্যবহার করা। ওভারফ্লো ইনসিনিকের জন্য জিসিসি ডকুমেন্টেশনগুলি 6.56 বিল্ট-ইন ফাংশন থেকে ওভারফ্লো চেকিংয়ের সাথে গাণিতিক সম্পাদন করতে পাওয়া যাবে ।


1
__uint128স্বাক্ষরিত ওভারফ্লো এবং ডান স্থানান্তরিত নেতিবাচক মান এড়াতে আপনার স্বাক্ষরযুক্ত 128-বিট প্রকারটি ব্যবহার করা উচিত ।
chqrlie

কি কি "কম্পাইলার নির্ভর সহজাত বুদ্ধির" এবং "ওভারফ্লো সহজাত বুদ্ধির" ? আপনি কি " অভ্যন্তরীণ ফাংশন " বলতে চান ? আপনার কি রেফারেন্স আছে? (দয়া করে আপনার উত্তর সম্পাদনা করে প্রতিক্রিয়া জানান , এখানে মন্তব্যে নয় (যথাযথ হিসাবে))
পিটার মর্টেনসেন

-3
#include <stdio.h>
#include <stdlib.h>

#define MAX 100 

int mltovf(int a, int b)
{
    if (a && b) return abs(a) > MAX/abs(b);
    else return 0;
}

main()
{
    int a, b;

    for (a = 0; a <= MAX; a++)
        for (b = 0; b < MAX; b++) {

        if (mltovf(a, b) != (a*b > MAX)) 
            printf("Bad calculation: a: %d b: %d\n", a, b);

    }
}

-3

এটি করার একটি পরিষ্কার উপায় হ'ল সমস্ত অপারেটর (+ এবং * বিশেষত) ওভাররাইড এবং ক্রিয়াকলাপ সম্পাদন করার আগে একটি ওভারফ্লো পরীক্ষা করা।


6
আপনি বিল্টিন টাইপের জন্য অপারেটরদের ওভাররাইড করতে পারবেন না Ex আপনার এটির জন্য ক্লাস লিখতে হবে এবং এটি ব্যবহারের জন্য ক্লায়েন্ট কোডটি পুনরায় লিখতে হবে।
ব্লেজারব্লেড

-3

এটি নির্ভর করে আপনি এটির জন্য কী ব্যবহার করেন। স্বাক্ষরবিহীন দীর্ঘ (DWORD) সংযোজন বা গুণন সম্পাদন করা, সেরা সমাধান হ'ল ULARGE_INTEGER ব্যবহার করা।

ULARGE_INTEGER দুটি ডিডাব্লোর্ডের একটি কাঠামো। উচ্চ মানটি "হাইপার্ট" হিসাবে অ্যাক্সেস করা থাকলে এবং নিম্ন ডিডব্লর্ডটি "লোয়ার পার্ট" হিসাবে অ্যাক্সেস করা হলে পুরো মানটি "কোয়াডপার্ট" হিসাবে অ্যাক্সেস করা যায়।

উদাহরণ স্বরূপ:

DWORD
My Addition(DWORD Value_A, DWORD Value_B)
{
    ULARGE_INTEGER a, b;

    b.LowPart = Value_A;  // A 32 bit value(up to 32 bit)
    b.HighPart = 0;
    a.LowPart = Value_B;  // A 32 bit value(up to 32 bit)
    a.HighPart = 0;

    a.QuadPart += b.QuadPart;

    // If  a.HighPart
    // Then a.HighPart contains the overflow (carry)

    return (a.LowPart + a.HighPart)

    // Any overflow is stored in a.HighPart (up to 32 bits)

6
দুর্ভাগ্যক্রমে, এটি একটি উইন্ডোজ-কেবল সমাধান। অন্যান্য প্ল্যাটফর্মগুলিতে নেই ULARGE_INTEGER
রহস্যময়

-3

নিম্নলিখিতটি ব্যবহারযোগ্য পোর্টেবল উপায়ে উপচে না গিয়ে স্বাক্ষরবিহীন গুণকে সম্পাদন করতে:

... /* begin multiplication */
unsigned multiplicand, multiplier, product, productHalf;
int zeroesMultiplicand, zeroesMultiplier;
zeroesMultiplicand = number_of_leading_zeroes( multiplicand );
zeroesMultiplier   = number_of_leading_zeroes( multiplier );
if( zeroesMultiplicand + zeroesMultiplier <= 30 ) goto overflow;
productHalf = multiplicand * ( c >> 1 );
if( (int)productHalf < 0 ) goto overflow;
product = productHalf * 2;
if( multiplier & 1 ){
   product += multiplicand;
   if( product < multiplicand ) goto overflow;
}
..../* continue code here where "product" is the correct product */
....
overflow: /* put overflow handling code here */

int number_of_leading_zeroes( unsigned value ){
   int ctZeroes;
   if( value == 0 ) return 32;
   ctZeroes = 1;
   if( ( value >> 16 ) == 0 ){ ctZeroes += 16; value = value << 16; }
   if( ( value >> 24 ) == 0 ){ ctZeroes +=  8; value = value <<  8; }
   if( ( value >> 28 ) == 0 ){ ctZeroes +=  4; value = value <<  4; }
   if( ( value >> 30 ) == 0 ){ ctZeroes +=  2; value = value <<  2; }
   ctZeroes -= x >> 31;
   return ctZeroes;
}

-4

ওভারফ্লো পরীক্ষা করার সহজ উপায় হ'ল বর্তমান মানটি আগের মানের চেয়ে কম কিনা তা যাচাই করে বৈধকরণ করা। উদাহরণস্বরূপ, ধরুন 2 এর পাওয়ারগুলি মুদ্রণের জন্য আপনার কাছে একটি লুপ রয়েছে:

long lng;
int n;
for (n = 0; n < 34; ++n)
{
   lng = pow (2, n);
   printf ("%li\n", lng);
}

আমি এতে ফলাফলগুলি বর্ণনা করার উপায়ে ওভারফ্লো পরীক্ষা করে যাচ্ছি:

long signed lng, lng_prev = 0;
int n;
for (n = 0; n < 34; ++n)
{
    lng = pow (2, n);
    if (lng <= lng_prev)
    {
        printf ("Overflow: %i\n", n);
        /* Do whatever you do in the event of overflow.  */
    }
    printf ("%li\n", lng);
    lng_prev = lng;
}

এটি স্বাক্ষরবিহীন মানগুলির পাশাপাশি ইতিবাচক এবং নেতিবাচক স্বাক্ষরিত উভয় মানের জন্য কাজ করে।

অবশ্যই, যদি আপনি মূল্যবৃদ্ধির পরিবর্তে মান হ্রাসের জন্য অনুরূপ কিছু করতে চান, তবে আপনি <=এটি তৈরি করতে সাইনটি উল্টিয়ে ফেলবেন >=, ধরে নিলেন আন্ডারফ্লো এর আচরণ ওভারফ্লোর আচরণের মতোই। সমস্ত সততার ক্ষেত্রে, এটি কোনও সিপিইউর ওভারফ্লো পতাকাটিতে অ্যাক্সেস ছাড়াই আপনি পোর্টেবল হিসাবে পাবেন (এবং এর জন্য ইনলাইন এসেম্বলি কোডের প্রয়োজন হবে, যাইহোক কার্যকরভাবে আপনার কোডটিকে অ-বহনযোগ্য করে তুলবে)।


9
যদি একটি স্বাক্ষরিত মান ওভারফ্লো হয় তবে আপনার প্রোগ্রামের আচরণটি সংজ্ঞায়িত। এটি চারপাশে মোড়ানো গ্যারান্টিযুক্ত হয় না।
ডেভিড স্টোন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.