does this condition suffice for overflow check in multiplication [duplicate] - c

This question already has answers here:
Catch and compute overflow during multiplication of two large integers
(14 answers)
Closed 9 years ago.
int isOverflow(uint a, uint b) {
// a and b are unsigned non-zero integers.
uint c = a * b;
if (c < ( a > b ? a : b))
return 1;
else
return 0;
}
Am I missing something ? I think the above snippet will work.
EDIT : I have seen other solutions like multiplication of large numbers, how to catch overflow which uses some fancy methods to check it. But to me above simple solution also looks correct. Thats why I am asking this question.

It's easy to prove this is wrong by finding an exception:
Consider these two 8-bit unsigned values: a = 0x1F and b = 0xF.
c = a * b
c = 0x1F * 0xF
c = 0xD1 (Overflow! The real answer is 0x1D1)
c < ( a > b ? a : b)
0xD1 < 0x1F => False (Wrong!)
A correct answer is here.

CERT has a great document INT30-C. Ensure that unsigned integer operations do not wrap which covers all the cases of unsigned integer overflow and check they advocate for multiplications requires that you test before you perform the multiplication to prevent the overflow before it occurs (I modified the example to fit your questions):
if (a > SIZE_MAX / b) {
/* Handle error condition */
}
c = a * b;
This is a straight forward solution to your problem, it has been solved and you should use the solutions that have been proven to work, coming up with your own solutions can be error prone.

Related

Received remark as comparison between signed and unsigned operands [duplicate]

This question already has answers here:
Comparison operation on unsigned and signed integers
(7 answers)
Closed 5 years ago.
I have a "C"code snippet as below
int32_t A = 5;
uint32_t B = 8;
if ( A >= B )
{
printf("Test");
}
When i build this i received an remark/warning as "comparison between signed and unsigned operands.Can any one address this issue?
Everything is ok while A is positive and B is less than 2^31.
But, if A is less than 0, then unexpected behavior occurs.
A = -1, in memory it will be saved as 0xFFFFFFFF.
B = 5, in memory it will be saved as 0x00000005.
When you do
if (A < B) {
//Something, you are expecting to be here
}
Compiler will compare them as unsigned 32-bit integer and your if will be expanded to:
if (0xFFFFFFFF < 0x00000005) {
//Do something, it will fail.
}
Compiler warns you about this possible problem.
Comparison operation on unsigned and signed integers
Good, very good! You are reading and paying attention to your compiler warnings.
In your code:
int32_t A = 5;
uint32_t B = 8;
if ( A >= B )
{
printf("Test");
}
You have 'A' as a signed int32_t value with min/max values of -2147483648/2147483647 and you have and unsigned uint32_t with min/max of 0/4294967295, respectively. The compiler generates the warning to guard against cases that are always true or false based on the types involved. Here A can never be greater than B for any values in the allowable range of B from 2147483648 - 4294967295. That whole swath of numbers will provide False regardless of the individual values involved.
Another great example would be if ( A < B ) which produces a TRUE for all values of A from -2147483648 - -1 because the unsigned type can never be less than zero.
The compiler warnings are there to warn that testing with these types may not provide valid comparisons for certain ranges of numbers -- that you might not have anticipated.
In the real world, if you know A is only holding values from 0 - 900, then you can simply tell the compiler that 1) you understand the warning and by your cast will 2) guarantee the values will provide valid tests, e.g.
int32_t A = 5;
uint32_t B = 8;
if (A >= 0 ) {
if ( (uint32_t)A >= B )
printf("Test");
}
else
/* handle error */
If you cannot make the guarantees for 1) & 2), then it is time to go rewrite the code in a way you are not faced with the warning.
Two good things happened here. You had compiler warnings enabled, and you took the time to read and understand what the compiler was telling you. This will come up time and time again. Now you know how to approach a determination of what can/should be done.

What does it mean if the bitwise XOR of the sum and two addends are both negative?

For example, there are 3 variables of long type, we add a and b and get s:
long a, b, s;
...
s = a + b
Now what does ((s^a) < 0 && (s^b) < 0) mean?
I saw a check like this in the source code of Python:
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
i = a + b;
if ((i^a) < 0 && (i^b) < 0)
goto slow_iadd;
x = PyInt_FromLong(i);
}
This code is wrong.
Assuming the usual 2's-complement rules of bitwise XOR for signed integers, then
(s^a) < 0
is the case if s and a have their sign bits set to opposite values. Thus,
((s^a) < 0 && (s^b) < 0)
indicates that s has sign different from both a and b, which must then have equal sign (pretending 0 is positive). If you added two integers of equal sign and got a result of different sign, there must have been an overflow, so this is an overflow check.
If we assume that signed overflow wraps, then s has opposite sign from a and b exactly when overflow has occurred. However, signed overflow is undefined behavior. Computing s is already wrong; we need to check whether the overflow would occur without actually performing the operation.
Python isn't supposed to do this. You can see what it's supposed to do in the Python 2 source code for int.__add__:
/* casts in the line below avoid undefined behaviour on overflow */
x = (long)((unsigned long)a + b);
if ((x^a) >= 0 || (x^b) >= 0)
It's supposed to cast to unsigned to get defined overflow behavior. The cast-to-unsigned fix was introduced in 5 different places as a result of issue 7406 on the Python bug tracker, but it looks like they missed a spot, or perhaps INPLACE_ADD was changed since then. I've left a message on the tracker.
I don't see how this is possible.
If (s^a) < 0, then the sign bit of either s or a must be a 1, so either s or a (but not both) must be negative. Same for s and b. So either s is negative and both a and b are positive, or s is positive and both a and b are negative. Both situations seem impossible.
Unless you count integer overflow/underflow, of course.

append numbers C Programming [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
If I have the number 88 how would I add 00 to the end of and turn it into 8800? Bitwise shifts is the only way I can think of to do this but it doesn't work. It completely changes the numbers.
Bitwise shifts can only be used to multiply by powers of two, you simply want multiplication. Just run:
printf("%d", 88 * 100);
to print 8800.
If all you want to do is literally add 00 to the end of numbers you can instead do:
printf("%d00", 88);
You cannot do everything with bitwise shift operators alone. Its mathematically impossible to say it straight. But if you still insist you can do something like (88 << 6) + (88 << 5) + (88 << 2)
As a comment points out your answer can be obtained simply by multiplying your number by hundred.
So, you read from a file, and want to add two zeroes to it. Two ways I can see to do this: String-wise and Numerically.
String-wise, you can use
strcat(inputedText, "00");
(or just printf, or possible other solutions)
numerically, you can convert the inputted data from the file to an int, and multiply it by 100. If you need to print it, Vality's answer shows how to do that.
Live run: http://ideone.com/wiW5Zb
#include <stdio.h>
#include <stdint.h>
int64_t calc(int64_t value)
{
int64_t t = 1;
while(t < value)
t *= 10;
return t;
}
int64_t concatnum(int64_t a, int64_t b)
{
return (a * calc(b)) + b;
}
int main()
{
int a = 1000;
int b = 11;
int c = concatnum(a, b); //b must be greater 10.
printf("%d", c);
return 0;
}

explicit MOD in C? [duplicate]

This question already has answers here:
How to code a modulo (%) operator in C/C++/Obj-C that handles negative numbers
(16 answers)
Closed 9 years ago.
Ok So I know and understand the difference between MOD and REM. I also am aware that C's % operation is a REM operation. I wanted to know, and could not find online, if there is some C library or function for an explicit MOD.
Specifically, I'd like (-1)%4 == 3 to be true. In C (-1)%4 = -1 since it is a remainder. And preferably I'd like to avoid using absolute values and even better would be to utilize some built in function that I can't seem to find.
Any advice will be much appreciated!
The best option I can think of is to compute:
((-1 % 4) + 4 ) % 4
Here you may replace -1 with any value and you will get MOD not REM.
The most common way to do what you expect is:
((a % b) + b ) % b
It works because (a % b) is a number in ]-b; b[ so (a % b) + b is positive (in ]0; 2 * b[) and adding b did not changed the mod.
Just do,
int mod(int a, int b)
{
int res = a % b;
return(res < 0 ? (res + b) : res);
}
Every negative res content after MOD operation is added to b to get modulus of a & b.

Fastest method for checking overflow? [duplicate]

This question already has answers here:
How do I detect unsigned integer overflow?
(31 answers)
Closed 5 years ago.
Here's my attempt. Any tips on a better solution?:
// for loop to convert 32 to 16 bits
uint32_t i;
int32_t * samps32 = (int32_t *)&(inIQbuffer[0]);
int16_t * samps16 = (int16_t *)&(outIQbuffer[0]);
for( i = 0; i < ( num_samples * 2/* because each sample is two int32 s*/ ); i++ ) {
overflowCount += ( abs(samps32[i]) & 0xFFFF8000 ) ? 1 : 0;
samps16[i] = (int16_t)samps32[i];
}
// Only report error every 4096 accumulated overflows
if( ( overflowCount & 0x1FFF ) > 4096 ) {
printf( "ERROR: Overflow has occured while scaling from 32 "
"bit to 16 bit samples %d times",
overflowCount );
}
Here's the part that actually checks for overflow:
overflowCount += ( abs(samps32[i]) & 0xFFFF8000 ) ? 1 : 0;
I personally prefer to use the SafeInt class to do my overflow checking. It reduces the need for tedious error checking and turns it into an easy to process, yet difficult to ignore exception.
http://blogs.msdn.com/david_leblanc/archive/2008/09/30/safeint-3-on-codeplex.aspx
What you already do, is closest to the fastests possible for a single cast. you can however omit some code
overflowCount += ( abs(samps32[i]) & 0xFFFF8000 ) ? 1 : 0;
can be changed into:
if (samps32[i] & 0xFFFF8000) overflowCount++;
or even simpler
if (samps32[i] >> 15) overflowCount++;
both of these will be equally fast, and both will be faster than yours.
If you are actually interrested in the count of overflows, you might consider processing the array of integers with SIMD operations.
It seems that you are checking for the overflow of a 16-bit addition. You can avoid branch in the assembler code by just having
overflowCount += (samps32[i] & 0x8000) >> 15;
This generates three ALU operations but no branch in the code. It may or may not be faster than a branching version.
Bit ops would be my choice, too. the only faster way I can imagine at the moment is to use inline assembly where you load the source operand, make a copy onboard the chip, truncate, and bitwise compare (that was pseudo pseudo code).
Your code has an issue: It violates aliasing rules. You could use something like this instead:
union conv_t {
int32_t i32;
int16_t i16;
};
Then you could ensure that IQBuffer is of that type. Finally, you could run:
for( i = 0; i < (num_samples * 2); i++ ) {
<test goes here>
samps [i].i16 = static_cast<int16_t>(samps [i].i32);
}
edit: As per your edit (https://stackoverflow.com/revisions/677427/list) you drove nearly my whole post invalid. Thanks for not mentioning your edit in your question.

Resources