I need to do the following calculation in a c++ code:
(((n*log(n)) / log(4)) + 1)
Where n is of type 'unsigned long long int' (and is a power of 2, so result should be integer).
For very large numbers i get some errors e.g for n = 9007199254740992 result should be 238690780250636289, but when i run the code i get 238690780250636288.
Could this be the result of 'log' function not having an implementation with 'unsigned long long int' argument? If so is there a way to circumvent it this without implementing a new log function?
unsigned long long int upToBit(unsigned long long int n) {
unsigned long long int check = (((n*log(n)) / log(4)) + 1);
return check;
}
Could this be the result of 'log' function not having an implementation with 'unsigned long long int' argument?
Yes and no.
You use std::log which returns double. double cannot represent 238690780250636289 because of the extended range. If you simply convert that number to long long, you'll get exactly the same error:
int main()
{
volatile double dd = 238690780250636289.0;
printf("%lld\n", (long long)dd);
}
Output:
238690780250636288
To understand why that happens, there is a good paper about floating point numbers.
You may have luck with long double version of log if sizeof(long double) is > 8 on your compiler. You may also test "correctness" of your computation:
bool resultOk = upToBit(9007199254740992) == 238690780250636289.0;
In general, double has 52-bit mantissa and because of extra hidden bit maximum reliable integer that double can represent is 2 power 53 or 9007199254740992. If your resulting double has higher integer value then simple integer math sometimes "stops working":
#include <stdio.h>
int main()
{
long long l = 9007199254740992;
double d = (double)l;
d += 1;
printf("9007199254740992 + 1 = %lld\n", (long long)d);
}
Output:
9007199254740992 + 1 = 9007199254740992
To get better precision you can use some of the multiple precision arithmetic libraries that are designed to do that. GCC for example uses GMP / MPFR for its internal calculations.
Related
There are 2 large integer numbers. When I multiply it the result is always wrong, even if I used long double and the result should be in valid range of long double:
long double f = 1000000000 * 99999;
I debugged, and the result is so strange: -723552768.00000000. Did I missed something? how can I multiple it?
Thanks and regard!
from the C++ standards:
4 An unsuffixed floating constant has type double. If suffixed by the
letter f or F, it has type float. If suffixed by the letter l or L, it
has type long double
auto fl = 1000000000.L * 99999.L;
std::cout << fl << "\n";
or
long double fl = 1000000000L * 99999.L;
std::cout <<"\n"<< fl << "\n";
Numeric literals are int by default in C++. Thus, the expression 1000000000 * 99999 is viewed as the multiplication of two int 's and therefore the result returned by the * operator is an int. This int is only converted to the long double variable f after the multiplication has taken place. Depending on your platform, the range of int is usually from -2147483648 to 2147483647 (or 4 bytes in size). However, the product of 1000000000 x 99999 is 9.9999 x 10^13 which falls outside this range and thus overflow occurs as the int variable is not large enough to hold the value.
To avoid this, at least one of the numbers the * operator operates on should be declared as a long double literal with the suffix .l or .L as follows:
long double f = 1000000000.L * 99999
In the above expression , the * operator will return a long double which is large enough to hold the resulting product before being assigned to f.
Agree with #feiXiang. You are basically multiplying two ints. To do correct calculations, you have to define large numbers as long double. See the code below:
#include <iostream>
using namespace std;
int main()
{
long double a = 1000000000;
long double b = 99999;
long double f = a * b;
cout<<f;
return 0;
}
Output:
9.9999e+13
Actually you invoke undefined behavior with:
long double f = 1000000000 * 99999;
First, evaluate 1000000000 * 99999, which is a multiplication of two int objects. Multiplying two int objects is always an int. Since int is not big enough to represent the result (most likely 32 bits), the upper bits are lost.
Since overflows in signed integer types is undefined, you just triggered undefined behavior. But in this case it is possible to explain what happened, even though it is UB.
The computation keeps only the lowest 32 bits, which should be (1000000000 * 99999) modulo (2**32) == 3571414528. But this value is too big for int. Since on PC int negatives are represented by two's complement, we have to subtract 2**32, every time 2**31<= result < 2**32. This gives -723552768
Now, the last step is:
long double f = -723552768
And that is what you see.
To overcome the issue, either use long long like this:
long double f = 1000000000LL * 99999;
Or double:
long double f = 1000000000.0 * 99999;
1000000000 and 99999 are integer numbers, then the result of 1000000000 * 99999 will be an integer before it is assigned to your variable, and the result is out of range of integer.
You should make sure that the result is a long double first:
long double f = (long double) 1000000000 * 99999;
Or
long double f = 1000000000LL * 99999;
This question already has answers here:
long long is 8 bytes, but I get integer overflow?
(1 answer)
Why does long long n = 2000*2000*2000*2000; overflow?
(6 answers)
Closed 5 years ago.
I have a simple c++ app that performs the following calculations
long long calcOne = 3 * 100000000; // 3e8, essentially
long long calcTwo = 3 * 1000000000; // 3e9, essentially
long long calcThree = 3 * 10000000000; // 3e10, essentially
If I write the result of each calculation I get the following output:
calcOne = 300000000
calcTwo = -1294967296
calcThree = 30000000000
So why does the second calculation fail? As far as I can tell it is within the limits of a long long type (calcThree was larger...).
I am using Visual Studio 2015 on Windows 10. Thanks in advance.
Integer constants are, by default ints.
1000000000
That can fit into an int. So, this constant gets parsed as an int. But multiplying it by 3 overflows int.
10000000000
This is too big to an int, so this constant is a long long, so the resulting multiplication does not overflow.
Solution: explicitly use long long constants:
long long calcOne = 3 * 100000000LL; // 3e8, essentially
long long calcTwo = 3 * 1000000000LL; // 3e9, essentially
long long calcThree = 3 * 10000000000LL; // 3e10, essentially
What you do with a result doesn't affect how that result is calculated. So the fact that you store the result in a long long doesn't change the fact that the numbers you multiplied in the second line of code were not long longs and so they overflowed. In the third line of code, the constant is a long long, so the multiplication is performed on long longs.
The compiler saw this
long long calcOne = (int) 3 * (int) 100000000; // 3e8, essentially
long long calcTwo = (int) 3 * (int) 1000000000; // 3e9, essentially
long long calcThree = (int) 3 * (long long) 10000000000; // 3e10, essentially
And so the calcTwo right hand value was inferred as an int type and then over flowed. You see the over flow as a negative long.
long long calcOne = 3LL * 100000000LL; // 3e8, essentially
long long calcTwo = 3LL * 1000000000LL; // 3e9, essentially
long long calcThree = 3LL * 10000000000LL; // 3e10, essentially
To avoid this in the future, be explicit as to the types of your static values.To tell the compiler a number is a long long post fix it with LL.
Most programming languages rank number types by size. The size/rank/type of a numeric expression is (usually) the type of the highest-ranked value in the expression.
Example: int * double -> double
Your program has:
long long int = int * int.
What's happening is that the result of int * int is an int. So your program will multiply first and treat the result in a signed integer (maximum value ~= 2 billion, so it wraps around into negative numbers). Then, this negative value gets stored in the long long int.
300 million (your first multiplication) fits in an int. No problem there. I'm guessing the third works properly because the compiler is smart enough to know that 30 billion doesn't fit in a 32-bit int and automatically gives it a 64-bit long long int.
Background: I have some elements in a record, where some elements can be float, unsigned int or unsigned long long. So, I though to use float as a common value to return from a function that reads those elements.
However, I am seeing this strange error on converting from unsigned int to float. On printing the value, it gets changed. How can I avoid it? Should I not return float from this function?
#include <iostream>
#include <limits>
using namespace std;
int main()
{
unsigned int myU = numeric_limits<unsigned int>::max();
cout<<" myU is "<<myU<<'\n'; //correct
float myF = (float) myU;
cout<<" back To Long "<<(unsigned long long ) myF<<'\n'; //error?
cout<<" back To unsigned int "<<(unsigned int ) myF<<'\n'; //error?
cout<<" to Float Without Fixed "<<(float) myU<<'\n';//not clear, so have to use fixed
cout<<" to Float With Fixed "<<fixed<<(float) myU<<'\n';//error?
cout<<" difference "<<myF-myU<<'\n'; //error?
cout<<" myU+32 "<<myU+32<<'\n'; //-1+32=31 ==> understandable
}
Output with gcc 4.6.3:
myU is 4294967295
back To Long 4294967296
back To unsigned int 0
to Float Without Fixed 4.29497e+09
to Float With Fixed 4294967296.000000
difference 1.000000
myU+32 31
The number 4294967295 in float (32-bit IEEE 754) is represented as follows:
0 10011111 00000000000000000000000
sign exponent mantissa
(+1) (2^32) (1.0)
The rule for converting it back to an integer (or long in this case) is:
sign * (2^exponent) * mantissa
and the result would be 4294967296 which is in appropriate size to fill long long for you but too big to be fit in unsigned int so you will get 0 for unsigned int conversion.
Note that the problem is the limitation of representing large numbers with float for example 4294967295 and 4294967200 both are representing the same bits when they are stored as floats.
The main issue you are seeing, is that a floating point type only provides a limited precision of its fraction part, which of course is natural since it can only hold so much information.
Now when you convert from unsigned int to float, the number you are using is too long to fit into the fraction part. Now that some precision was lost and you convert back to an integer format it may differ. To unsigned long long, the result is just one bigger, but in the conversion to unsigned int, you see an overflow happpening.
I'm confused with the C/C++ unsigned long long type because theoretically it should store up to 2^64-1 which is a number of 19 decimal digits, but the following code:
unsigned int x = 1000000u; //(One million)
unsigned long long k = (x*x);
cout << k << endl;
prints out 3567587328, which is not correct.
Now 1,000,000^2 results in 1,000,000,000,000 - a number of 12 decimal digit, way below the limit of even signed long long. How could this happen?
Does it have anything to do with the system I am running? (32-bit Ubuntu)
If I need a 64 bit system to implement a 64 bit operation then another question arises:
Most compilers use linear congruential generator to generate random numbers as follow:
x(t) = (a*x(t-1) + c) mod m.
a and c is usually a 32 bit big number, m is 2^32-1
So there is a big chance that a*x(t-1) results in a 64-bit number before the modulo operation is carried out.
If a 64 bit system is needed then how could gcc generate random numbers since 1990s on 16-32bit machines?
Thanks a million.
Sure k is unsigned long long, but x is unsigned int and hence so is x*x. Your expression is calculated as an unsigned int, which results in the usual wraparound when going over the limits of unsigned types. After the damage is done, it is converted to an unsigned long long.
Possible fixes:
make x an unsigned long long
unsigned long long k = ((unsigned long long)x*(unsigned long long)x);
unsigned long long k = (1ULL*x*x);
x is unsigned int --> x*x is unsigned int as well. In case the result of the multiplication exceeds the maximal value of unsigned int, wraparound occurs. Only after these operations the result is being assigned into the receiving variable (k). If you want the result to be unsigned long long you need to promote at least one of the operand to this type, e.g.: unsigned long long k = (unsigned long long)x * x;.
Regarding your second question: compilers usually do not generate numbers, that's done during runtime. I'm not sure where did you get the formulae x(t) = (a*x(t-1) + c) mod m. Assuming this is indeed the formula there are ways to keep the intermediate results bounded: the modulo operation can be applied to any operand or intermediate result without changing the outcome. Therefore x(t) = (a*x(t-1) + c) mod m = (a mod m) * (x(t-1) mod m) + c mod m.
When you multiply an unsigned int by an unsigned int on the right side, the result is an unsigned int. As such it has the same limits as the two numbers being multiplied, regardless of the fact that this value is subsequently assigned to an unsigned long long.
However, if you cast the unsigned int variables to unsigned long long, the result will be an unsigned long long and the value will not be limited to the size of an unsigned int.
unsigned long long k = (((unsigned long long)x)*((unsigned long long)x));
That should give you the result you want.
I'm doing a program that calculates the probability of lotteries.
Specification is choose 5 numbers out of 47 and 1 out of 27
So I did the following:
#include <iostream>
long int choose(unsigned n, unsigned k);
long int factorial(unsigned n);
int main(){
using namespace std;
long int regularProb, megaProb;
regularProb = choose(47, 5);
megaProb = choose(27, 1);
cout << "The probability of the correct number is 1 out of " << (regularProb * megaProb) << endl;
return 0;
}
long int choose(unsigned n, unsigned k){
return factorial(n) / (factorial(k) * factorial(n-k));
}
long int factorial(unsigned n){
long int result = 1;
for (int i=2;i<=n;i++) result *= i;
return result;
}
However the program doesn't work. The program calculates for 30 seconds, then gives me Process 4 exited with code -1,073,741,676 I have to change all the long int to long double, but that loses precision. Is it because long int is too short for the big values? Though I thought long int nowadays are 64bit? My compiler is g++ win32 (64bit host).
Whether long is 64-bit or not depends on the model. Windows uses a 32-bit long. Use int64_t from <stdint.h> if you need to ensure it is 64-bit.
But even if long is 64-bit it is still too small to hold factorial(47).
47! == 2.58623242e+59
2^64 == 1.84467441e+19
although 47C5 is way smaller than that.
You should never use nCr == n!/(r! (n-r)!) directly do the calculation as it overflows easily. Instead, factor out the n!/(n-r)! to get:
47 * 46 * 45 * 44 * 43
C = ----------------------
47 5 5 * 4 * 3 * 2 * 1
this can be managed even by a 32-bit integer.
BTW, for #Coffee's question: a double only has 53-bits of precision, where 47! requires 154 bits. 47! and 42! represented in double would be
47! = (0b10100100110011011110001010000100011110111001100100100 << 145) ± (1 << 144)
42! = (0b11110000010101100000011101010010010001101100101001000 << 117) ± (1 << 116)
so 47! / (42! × 5!)'s possible range of value will be
0b101110110011111110011 = 1533939 53 bits
v
max = 0b101110110011111110011.000000000000000000000000000000001001111...
val = 0b101110110011111110010.111111111111111111111111111111111010100...
min = 0b101110110011111110010.111111111111111111111111111111101011010...
that's enough to get the exact value 47C5.
to use 64bit long, you should use long long. (as mentioned here)
KennyTM has it right, you're going to overflow no matter what type you use. You need to approach the problem more smartly and factor out lots of work. If you're ok with an approximate answer, then take a look at Stirling's approximation:
Ln(n!) ~ n Ln(n) - n
So if you have
n!/(k!*(n-k)!)
You could say that's
e(ln(n!/(k!*(n-k)!)))
which after some math (double check to make sure I got it right) is
e(n*ln(n)-k*ln(k)-(n-k)*ln(n-k))
And that shouldn't overflow (but it's an approximate answer)
It's easy to calculate binomial coefficients up to 47C5 and beyond without overflow, using standard unsigned long 32-bit arithmetic. See my response to this question: https://math.stackexchange.com/questions/34518/are-there-examples-where-mathematicians-needs-to-calculate-big-combinations/34530#comment-76389