Is value of variable always negative in case of overflow - c++

It tried to solve this problem, given N,K amd M, find maximum integer T such that N*(K^T) <= M. N,K and M can be the values to 10^18. So long long is sufficient.
I tried to solve it using iteration on T
int T = 0;
long long Kpow = 1;
while(1)
{
long long prod = N*Kpow;
if(prod > M)
break;
T++;
Kpow = Kpow*K;
}
But since N*Kpow may go out of range of long long, there is need to handle the product using some big integer. But I found some other code which smartly handles this case
long long prod = N*Kpow;
if(prod < 0)
break;
Even I have seen always, that in overflow, the value of variable becomes negative. Is it always the case or sometimes even positive values also occur in overflow case?

From the point of view of the language, the behaviour of signed integer overflow is undefined. Which means anythign could happen - it can be negative, it can be unchanged, the program can crash or it can order pizza online.
What will most likely happen in practice depends on the processor architecture on which you're running - so you'd have to consult the platform specs to know.
But I'd guess you can't guarantee overflow to be negative. As a contrived example:
signed char c = 127;
c += 255;
std::cout << (int)c << '\n';
This happens to print 126 on x86. But again, it could actually do anything.

No. The value of variable is not always negative in case of overflow.
With signed integers, C11dr §3.7.1 3 undefined behavior "An example of undefined behavior is the behavior on integer overflow." so there is no test to do after overflow that is certain to work across compilers and platforms.
Detect potential overflow before it can happen.
int T = 0;
long long Kpow = 1;
long long Kpow_Max = LLONG_MAX/K;
long long prod_Max = LLONG_MAX/N;
while(1)
{
if (Kpow > prod_Max) Handle_Overflow();
long long prod = N*Kpow;
if(prod > M)
break;
T++;
if (Kpow > Kpow_Max) Handle_Overflow();
Kpow = Kpow*K;
}

Couldn't this problem be converted to K^T <= (M + N - 1) / N?
As far as overflow detection goes, normally addition and subtraction are performed as if the numbers were unsigned, with the overflow bit set based on signed math, and the carry / borrow bit set based on unsigned math. For multiplication, the low order of the result is the same for signed or unsigned multiply (this is why the ARM cpu only has a signed / unsigned multiply for 64 bit results from 32 bit operands). Overflow occurs if the product is too large to fit in the register that receives the product, like a 32 bit multiply that results in a 39 bit product, that is supposed to go into a 32 bit register. For divide, overflow can occur if the divisor is zero or if the quotient is too large to fit in the register that receives the quotient, for example a 64 bit dividend divided by a 32 bit divisor, resulting in a 40 bit quotient. For multiply and divide, it doesn't matter if the operands are signed or not, only if the size of the result will fit in the register that receives the result.

Just as in any other situation with signed integers of any length...overflow makes the number negative if and only if the specific bit which is overflowed into the sign bit is on.
Meaning if the result of your arithmetic would give you an overflow which, if you were to double the length of your variable word, would leave your current sign bit as off, you could quite possibly come up with an erroneous result which is positive.

Related

"Symmetrical difference" for unsigned ints - assumed rollover

I made a simple function that I called symmetricDelta() which calculates the delta between value and previous "symmetrically". What I mean by that is: consider a number-line from e.g. 0 to ULLONG_MAX, where you connected the left and right ends of the number-line... To determine a "symmetric" delta, assume the change is positive if value - previous is less than half of the span, otherwise assume the change is negative, and we wrapped-around the number-line.
See a simple version of this for uint64_ts below:
int64_t symmetricDelta(uint64_t value, uint64_t previous) {
if (value-previous < (1ULL << 63)) {
uint64_t result = value - previous;
return result;
} else {
uint64_t negativeResult = previous - value;
return -1 * negativeResult;
}
}
Usage:
uint64_t value = ULLONG_MAX;
uint64_t previous = 0;
// Result: -1, not UULONG_MAX
cout << symmetricDelta(value, previous) << endl;
Demo: https://onlinegdb.com/BJ8FFZgrP
Other value examples, assume a uint8_t version for simplicity:
symmetricalDifference(1, 0) == 1
symmetricalDifference(0, 1) == -1
symmetricalDifference(0, 255) == 1
symmetricalDifference(255, 0) == -1
symmetricalDifference(227, 100) == 127
symmetricalDifference(228, 100) == -128
My question is: Is there an "official" name for what I'm calling "symmetrical subtraction"? This feels like the kind of thing that might already be implemented in the C++ STL, but I wouldn't even know what to search for...
Yes. The name is subtraction modulo 2^64. And it's identical to what your machine does with the instruction
int64_t symmetricDelta(uint64_t value, uint64_t previous) {
return (int64_t)(value-previous);
}
In C and C++, unsigned arithmetic is defined to wrap around, effectively joining the ends of the representable number range into a circle. This is the basis for the 2-complement representation of signed integers: Your CPU simply declares half the number circle to be interpreted negative. This part is the upper part in unsigned, with the -1 corresponding to the maximum representable unsigned integer. Simply because the 0 is next on the circle.
Side note:
This allows the CPU to use the exact same circuitry for signed and unsigned arithmetic. The CPU only provides an add instruction that is used irrespective of whether the numbers should be interpreted as signed or unsigned. This is true for addition, subtraction and multiplication, they all exist as sign-ignorant instructions. Only the division is implemented in a signed and an unsigned variant, as are the comparison instructions / the flag bits that the CPU provides.
Side note 2:
The above is not fully true, as modern CPUs implement saturating arithmetic as part of their vector units (AVX etc.). Because saturating arithmetic means clipping the result to the ends of the representable range instead of wrapping around, this clipping depends on where the circle of numbers is assumed to be broken. As such, saturating arithmetic instructions typically exist in signed and unsigned variants.
End of the needless background rambling...
So, when you subtract two numbers in unsigned representation, the result is the unsigned number of steps that you have to take to reach the minuend from the subtrahend. And by reinterpreting the result as a signed integer, you are interpreting a long route (that goes more than half around the circle) as the corresponding short route in the opposite direction.
There is one pitfall: 1 << 63 is not representable. It is exactly on the opposite side of the number circle from the zero, and since its sign bit is set, it's interpreted as -(1 << 63). If you try to negate it, the bit pattern does not change one bit (just like -0 == 0), so your computer happily declares that - -(1 << 63) == -(1 << 63). This is probably not a problem to you, but it's better to be aware of this, because it might bite you.

why declare "score[11] = {};" and "grade" as "unsigned" instead of "int'

I'm new to C++ and is trying to learn the concept of array. I saw this code snippet online. For the sample code below, does it make any difference to declare:
unsigned scores[11] = {};
unsigned grade;
as:
int scores[11] = {};
int grade;
I guess there must be a reason why score[11] = {}; and grade is declared as unsigned, but what is the reason behind it?
int main() {
unsigned scores[11] = {};
unsigned grade;
while (cin >> grade) {
if (0 <= grade <= 100) {
++scores[grade / 10];
}
}
for (int i = 0; i < 11; i++) {
cout << scores[i] << endl;
}
}
unsigned means that the variable will not hold a negative values (or even more accurate - It will not care about the sign-). It seems obvious that scores and grades are signless values (no one scores -25). So, it is natural to use unsigned.
But note that: if (0 <= grade <= 100) is redundant. if (grade <= 100) is enough since no negative values are allowed.
As Blastfurnace commented, if (0 <= grade <= 100) is not right even. if you want it like this you should write it as:
if (0 <= grade && grade <= 100)
Unsigned variables
Declaring a variable as unsigned int instead of int has 2 consequences:
It can't be negative. It provides you a guarantee that it never will be and therefore you don't need to check for it and handle special cases when writing code that only works with positive integers
As you have a limited size, it allows you to represent bigger numbers. On 32 bits, the biggest unsigned int is 4294967295 (2^32-1) whereas the biggest int is 2147483647 (2^31-1)
One consequence of using unsigned int is that arithmetic will be done in the set of unsigned int. So 9 - 10 = 4294967295 instead of -1 as no negative number can be encoded on unsigned int type. You will also have issues if you compare them to negative int.
More info on how negative integer are encoded.
Array initialization
For the array definition, if you just write:
unsigned int scores[11];
Then you have 11 uninitialized unsigned int that have potentially values different than 0.
If you write:
unsigned int scores[11] = {};
Then all int are initialized with their default value that is 0.
Note that if you write:
unsigned int scores[11] = { 1, 2 };
You will have the first int intialized to 1, the second to 2 and all the others to 0.
You can easily play a little bit with all these syntax to gain a better understanding of it.
Comparison
About the code:
if(0 <= grade <= 100)
as stated in the comments, this does not do what you expect. In fact, this will always evaluate to true and therefore execute the code in the if. Which means if you enter a grade of, say, 20000, you should have a core dump. The reason is that this:
0 <= grade <= 100
is equivalent to:
(0 <= grade) <= 100
And the first part is either true (implicitly converted to 1) or false (implicitly converted to 0). As both values are lower than 100, the second comparison is always true.
unsigned integers have some strange properties and you should avoid them unless you have a good reason. Gaining 1 extra bit of positive size, or expressing a constraint that a value may not be negative, are not good reasons.
unsigned integers implement arithmetic modulo UINT_MAX+1. By contrast, operations on signed integers represent the natural arithmetic that we are familiar with from school.
Overflow semantics
unsigned has well defined overflow; signed does not:
unsigned u = UINT_MAX;
u++; // u becomes 0
int i = INT_MAX;
i++; // undefined behaviour
This has the consequence that signed integer overflow can be caught during testing, while an unsigned overflow may silently do the wrong thing. So use unsigned only if you are sure you want to legalize overflow.
If you have a constraint that a value may not be negative, then you need a way to detect and reject negative values; int is perfect for this. An unsigned will accept a negative value and silently overflow it into a positive value.
Bit shift semantics
Bit shift of unsigned by an amount not greater than the number of bits in the data type is always well defined. Until C++20, bit shift of signed was undefined if it would cause a 1 in the sign bit to be shifted left, or implementation-defined if it would cause a 1 in the sign bit to be shifted right. Since C++20, signed right shift always preserves the sign, but signed left shift does not. So use unsigned for some kinds of bit twiddling operations.
Mixed sign operations
The built-in arithmetic operations always operate on operands of the same type. If they are supplied operands of different types, the "usual arithmetic conversions" coerce them into the same type, sometimes with surprising results:
unsigned u = 42;
std::cout << (u * -1); // 4294967254
std::cout << std::boolalpha << (u >= -1); // false
What's the difference?
Subtracting an unsigned from another unsigned yields an unsigned result, which means that the difference between 2 and 1 is 4294967295.
Double the max value
int uses one bit to represent the sign of the value. unsigned uses this bit as just another numerical bit. So typically, int has 31 numerical bits and unsigned has 32. This extra bit is often cited as a reason to use unsigned. But if 31 bits are insufficient for a particular purpose, then most likely 32 bits will also be insufficient, and you should be considering 64 bits or more.
Function overloading
The implicit conversion from int to unsigned has the same rank as the conversion from int to double, so the following example is ill formed:
void f(unsigned);
void f(double);
f(42); // error: ambiguous call to overloaded function
Interoperability
Many APIs (including the standard library) use unsigned types, often for misguided reasons. It is sensible to use unsigned to avoid mixed-sign operations when interacting with these APIs.
Appendix
The quoted snippet includes the expression 0 <= grade <= 100. This will first evaluate 0 <= grade, which is always true, because grade can't be negative. Then it will evaluate true <= 100, which is always true, because true is converted to the integer 1, and 1 <= 100 is true.
Yes it does make a difference. In the first case you declare an array of 11 elements a variable of type "unsigned int". In the second case you declare them as ints.
When the int is on 32 bits you can have values from the following ranges
–2,147,483,648 to 2,147,483,647 for plain int
0 to 4,294,967,295 for unsigned int
You normally declare something unsigned when you don't need negative numbers and you need that extra range given by unsigned. In your case I assume that that by declaring the variables unsigned, the developer doesn't accept negative scores and grades. You basically do a statistic of how many grades between 0 and 10 were introduced at the command line. So it looks like something to simulate a school grading system, therefore you don't have negative grades. But this is my opinion after reading the code.
Take a look at this post which explains what unsigned is:
what is the unsigned datatype?
As the name suggests, signed integers can be negative and unsigned cannot be. If we represent an integer with N bits then for unsigned the minimum value is 0 and the maximum value is 2^(N-1). If it is a signed integer of N bits then it can take the values from -2^(N-2) to 2^(N-2)-1. This is because we need 1-bit to represent the sign +/-
Ex: signed 3-bit integer (yes there are such things)
000 = 0
001 = 1
010 = 2
011 = 3
100 = -4
101 = -3
110 = -2
111 = -1
But, for unsigned it just represents the values [0,7]. The most significant bit (MSB) in the example signifies a negative value. That is, all values where the MSB is set are negative. Hence the apparent loss of a bit in its absolute values.
It also behaves as one might expect. If you increment -1 (111) we get (1 000) but since we don't have a fourth bit it simply "falls off the end" and we are left with 000.
The same applies to subtracting 1 from 0. First take the two's complement
111 = twos_complement(001)
and add it to 000 which yields 111 = -1 (from the table) which is what one might expect. What happens when you increment 011(=3) yielding 100(=-4) is perhaps not what one might expect and is at odds with our normal expectations. These overflows are troublesome with fixed point arithmetic and have to be dealt with.
One other thing worth pointing out is the a signed integer can take one negative value more than it can positive which has a consequence for rounding (when using integer to represent fixed point numbers for example) but am sure that's better covered in the DSP or signal processing forums.

Can n %= m ever return negative value for very large nonnegative n and m?

This question is regarding the modulo operator %. We know in general a % b returns the remainder when a is divided by b and the remainder is greater than or equal to zero and strictly less than b. But does the above hold when a and b are of magnitude 10^9 ?
I seem to be getting a negative output for the following code for input:
74 41 28
However changing the final output statement does the work and the result becomes correct!
#include<iostream>
using namespace std;
#define m 1000000007
int main(){
int n,k,d;
cin>>n>>k>>d;
if(d>n)
cout<<0<<endl;
else
{
long long *dp1 = new long long[n+1], *dp2 = new long long[n+1];
//build dp1:
dp1[0] = 1;
dp1[1] = 1;
for(int r=2;r<=n;r++)
{
dp1[r] = (2 * dp1[r-1]) % m;
if(r>=k+1) dp1[r] -= dp1[r-k-1];
dp1[r] %= m;
}
//build dp2:
for(int r=0;r<d;r++) dp2[r] = 0;
dp2[d] = 1;
for(int r = d+1;r<=n;r++)
{
dp2[r] = ((2*dp2[r-1]) - dp2[r-d] + dp1[r-d]) % m;
if(r>=k+1) dp2[r] -= dp1[r-k-1];
dp2[r] %= m;
}
cout<<dp2[n]<<endl;
}
}
changing the final output statement to:
if(dp2[n]<0) cout<<dp2[n]+m<<endl;
else cout<<dp2[n]<<endl;
does the work, but why was it required?
By the way, the code is actually my solution to this question
This is a limit imposed by the range of int.
int can only hold values between –2,147,483,648 to 2,147,483,647.
Consider using long long for your m, n, k, d & r variables. If possible use unsigned long long if your calculations should never have a negative value.
long long can hold values from –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
while unsigned long long can hold values from 0 to 18,446,744,073,709,551,615. (2^64)
The range of positive values is approximately halved in signed types compared to unsigned types, due to the fact that the most significant bit is used for the sign; When you try to assign a positive value greater than the range imposed by the specified Data Type the most significant bit is raised and it gets interpreted as a negative value.
Well, no, modulo with positive operands does not produce negative results.
However .....
The int type is only guaranteed by the C standards to support values in the range -32767 to 32767, which means your macro m is not necessarily expanding to a literal of type int. It will fit in a long though (which is guaranteed to have a large enough range).
If that's happening (e.g. a compiler that has a 16-bit int type and a 32-bit long type) the results of your modulo operations will be computed as long, and may have values that exceed what an int can represent. Converting that value to an int (as will be required with statements like dp1[r] %= m since dp1 is a pointer to int) gives undefined behaviour.
Mathematically, there is nothing special about big numbers, but computers only have a limited width to write down numbers in, so when things get too big you get "overflow" errors. A common analogy is the counter of miles traveled on a car dashboard - eventually it will show as all 9s and roll round to 0. Because of the way negative numbers are handled, standard signed integers don't roll round to zero, but to a very large negative number.
You need to switch to larger variable types so that they overflow less quickly - "long int" or "long long int" instead of just "int", the range doubling with each extra bit of width. You can also use unsigned types for a further doubling, since no range is used for negatives.

getting random numbers larger than RAND_MAX

Question 7-9 of Accelerated C++ by Andrew Koenig asks:
7-9. (difficult) The implementation of nrand in §7.4.4/135 will not
work for arguments greater than RAND_MAX. Usually, this restriction is
no problem, because RAND_MAX is often the largest possible integer
anyway. Nevertheless, there are implementations under which RAND_MAX
is much smaller than the largest possible integer. For example, it is
not uncommon for RAND_MAX to be 32767 (2^15 -1) and the largest
possible integer to be 2147483647 (2^31 -1). Reimplement nrand so that
it works well for all values of n.
If n > RAN_MAX my thoughts are to take
double temp = n/RAN_MAX + .5;
int mult = temp;
int randomNum = 0;
for (int i = 0; i != mult; mult++)
randomNum += rand();
then test to see if randomNum < n. Would this work to generate a random number > RAND_MAX? I don't know how to use larger integers than my computer can handle, so I don't think there is any real way to tell.
If you're truly mucking with integers larger than your computer can handle, that's, well, complicated.
But you do have several options for integers big than int, these include: unsigned int, long, unsigned long, long long, unsigned long long in increasing order of bigness. Just how big the numbers become various depending on your architecture.
For instance, on my machine I have the following:
Data Type: Bytes Minimum Maximum
Short SInt: 2 -32768 32767
Short UInt: 2 0 65535
UInt: 4 0 4294967295
SInt: 4 -2147483648 2147483647
ULong: 8 0 18446744073709551615
SLong: 8 -9223372036854775808 9223372036854775807
ULong Long: 8 0 18446744073709551615
SLong Long: 8 -9223372036854775808 9223372036854775807
So, as you can see, you can make numbers much larger than int and 32767.
One way to do this is as follows:
double a=rand()/(double)RAND_MAX;
unsigned long long random_n=(unsigned long long)(BIG_MAXIMUM_NUMBER*a);
However, due to the discrete nature of floating-point numbers, this may mean that some values will just never show up in your output stream.
C++11 has a library which solves both this problem and the problem you mention. An example of its usage is:
const int min = 100000;
const int max = 1000000;
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(min,max);
int random_int = distribution(generator);
Just change the data types to suit your big needs.
Another way to look at this is that we can interpret rand() as returning a bit-field and that, since it is a uniform PRNG, all bit-fields are equally likely. We can then just make multiple calls to rand() to get multiple equally-likely bit-fields and merge these to make big numbers. Here's how we would do this to make a 16-bit random number from two 8-bit random numbers:
uint16 a=(uint16)(rand()&255);
uint16 b=(uint16)(rand()&255);
uint16 random_int=b<<8 | a;
The rand()&255 keeps only the 8 least significant bits of whatever number rand() returns; that is, it keeps only the last byte of rand().
The (uint16) casts this byte into an unsigned 16-bit number.
a<<8 shifts the bits of a 8 bits to the left, which makes room to safely add b.
But what if rand() returns a signed-value, such that the most-significant bit is always 0 or 1? We can then do the following:
uint16 a=(uint16)(rand()&255);
uint16 b=(uint16)(rand()&255);
uint16 c=(uint16)(rand()&1);
uint16 random_int=c<<14 | b<<7 | a;
We left-shift b only 7-bits so that the 8th least significant bit is random. This means the 14th and 15th least significant bits will be non-random. Since we want to mimic the behaviour of rand(), we leave the 15th least significant bit non-random, and grab a single random bit to left-shift into the 14th LSB's place.

Negation of -2147483648 not possible in C/C++?

#include <iostream>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int num=-2147483648;
int positivenum=-num;
int absval=abs(num);
std::cout<<positivenum<<"\n";
std::cout<<absval<<"\n";
return 0;
}
Hi I am quite curious why the output of the above code is
-2147483648
-2147483648
Now I know that -2147483648 is the smallest represntable number among signed ints, (assuming an int is 32 bits). I would have assumed that one would get garbage answers only after we went below this number. But in this case, +2147483648 IS covered by the 32 bit system of integers. So why the negative answer in both cases?
But in this case, +2147483648 IS covered by the 32 bit system of integers.
Not quite correct. It only goes up to +2147483647. So your assumption isn't right.
Negating -2147483648 will indeed produce 2147483648, but it will overflow back to -2147483648.
Furthermore, signed integer overflow is technically undefined behavior.
The value -(-2147483648) is not possible in 32-bit signed int. The range of signed 32-bit int is –2147483648 to 2147483647
Ahhh, but its not... remember 0, largest signed is actually 2147483647
Because the 2's complement representation of signed integers isn't symmetric and the minimum 32-bit signed integer is -2147483648 while the maximum is +2147483647. That -2147483648 is its own counterpart just as 0 is (in the 2's complement representation there's only one 0, there're no distinct +0 and -0).
Here's some explanation.
A negative number -X when represented as N-bit 2's complement, is effectively represented as unsigned number that's equal to 2N-X. So, for 32-bit integers:
if X = 1, then -X = 232 - 1 = 4294967295
if X = 2147483647, then -X = 232 - 2147483647 = 2147483649
if X = 2147483648, then -X = 232 - 2147483648 = 2147483648
if X = -2147483648, then -X = 232 + 2147483648 = 2147483648 (because we only keep low 32 bits)
So, -2147483648 = +2147483648. Welcome to the world of 2's complement values.
The previous answers have all pointed out that the result is UB (Undefined Behaviour) because 2147483648 is not a valid int32_t value. And we all know, UB means anything can happen, including having daemons flying out of your nose. The question is, why does the cout behavior print out a negative value, which seems to be the worst value it could have chosen randomly ?
I'll try to justify it on a two's complement system. Negation on a CPU is actually somewhat of a tricky operation. You can't do it in one step. One way of implementing negation, i.e. int32_t positivenum = -num is to do a bit inversion followed by adding 1, i.e. int32_t positivenum = ~num + 1, where ~ is the bitwise negation operator and the +1 is to fix the off-by-one error. For example, negation of 0x00000000 is 0xFFFFFFFF + 1 which is 0x00000000 (after roll over which is what most CPUs do). You can verify that this works for most integers... except for 2147483648. 2147483648 is stored as 0x80000000 in two's complement. When you invert and add one, you get
- (min) = -(0x80000000)
= ~(0x80000000) + 1
= 0x7FFFFFFF + 1
= 0x80000000
= min
So magically, the unary operator - operating on min gives you back min!
One thing that is not obvious is that two-complement CPUs' arithmetic have no concept of positive or negative numbers! It treats all numbers as unsigned under the hood. There is just one adder circuit, and one multiplier circuit. The adder circuit works for positive and negative numbers, and the multiplier circuit works for positive and negative number.
Example: -1 * -1
= -1 * -1
= (cast both to uint32_t)
= 0xFFFFFFFF * 0xFFFFFFFF
= FFFFFFFE00000001 // if you do the result to 64 bit precision
= 0x00000001 // after you truncate to 32 bit precision
= 1
The only time you care about signed vs unsigned is for comparisons, like < or >.