Floating point exception in C - c

#include <stdio.h>
#include <math.h>
#include <string.h>
long fctl(int n){
int a=1,i;
for(i=n;i>1;--i)
a*=i;
return a;
}
long ch(int n, int r){
return fctl(n) / (fctl(n-r)*fctl(r));
}
int main(){
char *hands[] = {"onepair", "twopair", "triple", "straight", "flush", "fullhouse", "fourofakind", "straightflush", "royalflush"};
double handprobs[9];
handprobs[0] = ch(13,1)*ch(4,2) * ch(12,3)*pow(ch(4,1), 3) / ch(52,5);
handprobs[1] = ch(13,2)*pow(ch(4,2), 2) * ch(11,1)*ch(4,1) / ch(52,5);
handprobs[2] = ch(13,1)*ch(4,3) * ch(12,2)*pow(ch(4,1), 2) / ch(52,5);
handprobs[3] = 10.0 * pow(ch(4, 1),5) / ch(52, 5) - 10.0/ch(52,5) - 4.0/ch(52,5);
handprobs[4] = ch(13,5)*ch(4,1) / ch(52, 5) - 10.0/ch(52,5);
handprobs[5] = ch(13,1)*ch(4,3) * ch(12,1)*ch(4,2) / ch(52,5);
handprobs[6] = ch(13,1)*1 * ch(12,1)*ch(4,1) / ch(52,5);
handprobs[7] = 40.0 / ch(52, 5) - 4.0/ch(52,5),
handprobs[8] = 4.0 / ch(52, 5);
int i;
for(i=0;hands[i];++i){
printf("%s\t%f\n",hands[i], handprobs[i]);
}
}
When I compile it returns "Floating point exception (core dumped)", not sure why. (Have tried converting all the probs with (double).) Any ideas?

fctl(52) is waaaaay too big for an int. You're going to have to rethink your approach to doing this calculation. You can output INT_MAX to see how far you can actually go. You can buy a tiny bit more space by using unsigned long long (cf. ULLONG_MAX) but that is still nowhere near big enough for 52! .
Invoking integer overflow causes undefined behaviour; "floating point exception" often means attempt to do integer division by zero, which is plausible given your attempted calculations plus the fact that they overflowed. Don't ask me why this is reported as FPE despite the fact that it didn't involve any floating point. (probably "historical reasons")

After accept answer.
#Matt McNabb wells points out that fctl(52) is certianly to big for a vaid numeric result to fit in an long. (#mrVoid asserts 225 bit int needed.)
But certain #Lưu Vĩnh Phúc is on the right track as to what caused the exception.
fctl(x) will be the product of numbers 1 to x, half of those are even. Thus fctl(x) will have x/2 LSbits set to zero.
Assuming 32-bit int, once the number of LSBits of fctl(n-r) and fctl(r) exceed/meet 32, the product (fctl(n-r)*fctl(r)) will be 0 and return fctl(n) / (0); throws an exception.
On many systems an integer divide by 0 is reported as an floating-point error. I think this oddity occurs to simplify trap handling.

Related

Why is pow() function in C giving wrong answer when it is odd exponential of 10 in a loop? [duplicate]

This question already has answers here:
Why pow(10,5) = 9,999 in C++
(8 answers)
Closed 2 years ago.
#include <stdio.h>
#include <math.h>
int main()
{
int loop, place_value=0, c = 5;
for(loop = 0; loop < c; loop++)
{
place_value = 0;
place_value = pow(10, loop);
printf("%d \n", place_value);
}
return 0;
}
This code gives
10
99
1000
9999
Why is 99 and 9999 there in 3rd and 5th line instead of 100 and 10000 respectively?
When asking for power normally, it gives right answer.
#include <stdio.h>
#include <math.h>
int main()
{
printf ("%d", (int) pow (10,3 ));
return 0;
}
1000
pow is a difficult routine to implement, and not all implementations give good results. Roughly speaking, the core algorithm for pow(x, y) computes a logarithm from (a part of) x, multiplies it by y, and computes an exponential function on the product. Doing this in floating-point introduces rounding errors that are hard to control.
The result is that the computed result for pow(10, 4) may be something near 10,000 but slightly less or greater. If it is less, than converting it to an integer yields 9999.
When you use arguments hard-coded in source code, the compiler may compute the answer during compilation, possibly using a different algorithm. For example, when y is three, it may simply multiply the first argument by itself, as in x*x*x, rather than using the logarithm-exponent algorithm.
As for why the low result happens with the odd numbers you have tested, consider what happens when we multiply 5.45454545 by various powers of 10 and round to an integer. 5.45454545 rounds down to 5. 54.5454545 rounds up to 55. 545.454545 rounds down to 545. The rounding up or down is a consequence of what fraction happens to land beyond the decimal point. For your cases with pow(10, loop), the bits of the logarithm of 10 may just happen to give this pattern with the few odd numbers you tried.
pow(x, y) function translate more or less to exp(log(x) * y), which will give a result that is not quite the same as x ^ y.
In order to solve this issue you can round this:
round(pow(x, y))
The rule of thumb: never use floating point functions (especially such a complicated ones like pow or log) with integer numbers.
Simply implement integer pow
unsigned intpow(unsigned x)
{
unsigned result = 1;
while(x --) result *= 10;
return result;
}
it will be much faster or even (the fastest one)
int intpow1(unsigned x)
{
const static unsigned vals[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, /* ... */};
#if defined(CHECK_OVERFLOW)
if(x >= sizeof(vals)/ sizeof(vals[0])) return -1;
#endif
return vals[x];
}

pow() function giving wrong answer [duplicate]

This question already has an answer here:
pow() function in C problems [duplicate]
(1 answer)
Closed 3 years ago.
I'm trying to multiply 2, 3 digit numbers.
I used 2 for loops (nested) and multiplied each digit of num1 with num2,
and shifted each result to the appropriate place using pow().
So the problem is pow(10,3) is coming out to be 299 instead of 300.
I haven't tried much as but used printf to find what is actually happening in the runtime and this is what I have found.
the values of tempR after shift should be
5,40,300,100,800,6000,1500,12000,90000
but are coming as
5,40,299,100,799,6000,1500,12000,89999
int main(void)
{
int result; // final result
int tempR; // temporary for each iteration
char a[] = "345"; // number 1
char b[] = "321"; // number 2
for(int i = 2;i>= 0 ; i --)
{
for(int j = 2;j >= 0 ; j --)
{
int shift = abs(i-2 + j -2);
printf("%d\n",shift); //used to see the values of shift.
//and it is coming as expected
tempR = (int)(b[i] - '0') * (int)(a[j] - '0');
printf("%d \n",tempR); // value to tempR is perfect
tempR = tempR*pow(10,shift);
printf("%d \n",tempR); // here the problem starts
result += tempR;
}
}
printf("%d",result);
}
Although IEEE754 (ubiquitous on desktop systems) is required to return the best possible floating point value for certain operators such as addition, multiplication, division, and subtraction, and certain functions such as sqrt, this does not apply to pow.
pow(x, y) can and often is implemented as exp(y * ln (x)). Hopefully you can see that this can cause result to "go off" spectacularly when pow is used with seemingly trivial integral arguments and the result truncated to int.
There are C implementations out there that have more accurate implementations of pow than the one you have, particularly for integral arguments. If such accuracy is required, then you could move your toolset to such an implementation. Borrowing an implementation of pow from a respected mathematics library is also an option, else roll your own. Using round is also a technique, if a little kludgy if you get my meaning.
Never use float functions for the integer calculations. Your pow result almost never will be precise. In this case it is slightly below 300 and the cast to integer makes it 299.
The pow function operates on doubles. Doubles use finite precision. Conversion back to integer chops rather than rounding.
Finite precision is like representing 1/3 as 0.333333. If you do 9 * 1/3 and chop to an integer, you'll get 2 instead of 3 because 9 * 1/3 will give 2.999997 which chops to two.
This same kind of rounding and chopping is causing you to be off by one. You could also round by adding 0.5 before chopping to an integer, but I wouldn't suggest it.
Don't pass integers through doubles and back if you expect exact answers.
Others have mentioned that pow does not yield exact results, and if you convert the result to an integer there's a high risk of loss of precision. Especially since if you assign a float type to an integer type, the result get truncated rather than rounded. Read more here: Is floating math broken?
The most convenient solution is to write your own integer variant of pow. It can look like this:
int int_pow(int num, int e)
{
int ret = 1;
while(e-- > 0)
ret *= num;
return ret;
}
Note that it will not work if e is negative or if both num and e is 0. It also have no protection for overflow. It just shows the idea.
In your particular case, you could write a very specialized variant based on 10:
unsigned int pow10(unsigned int e)
{
unsigned int ret = 1;
while(e-- > 0)
ret *= 10;
return ret;
}

C - erroneous output after multiplication of large numbers

I'm implementing my own decrease-and-conquer method for an.
Here's the program:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
double dncpow(int a, int n)
{
double p = 1.0;
if(n != 0)
{
p = dncpow(a, n / 2);
p = p * p;
if(n % 2)
{
p = p * (double)a;
}
}
return p;
}
int main()
{
int a;
int n;
int a_upper = 10;
int n_upper = 50;
int times = 5;
time_t t;
srand(time(&t));
for(int i = 0; i < times; ++i)
{
a = rand() % a_upper;
n = rand() % n_upper;
printf("a = %d, n = %d\n", a, n);
printf("pow = %.0f\ndnc = %.0f\n\n", pow(a, n), dncpow(a, n));
}
return 0;
}
My code works for small values of a and n, but a mismatch in the output of pow() and dncpow() is observed for inputs such as:
a = 7, n = 39
pow = 909543680129861204865300750663680
dnc = 909543680129861348980488826519552
I'm pretty sure that the algorithm is correct, but dncpow() is giving me wrong answers.
Can someone please help me rectify this? Thanks in advance!
Simple as that, these numbers are too large for what your computer can represent exactly in a single variable. With a floating point type, there's an exponent stored separately and therefore it's still possible to represent a number near the real number, dropping the lowest bits of the mantissa.
Regarding this comment:
I'm getting similar outputs upon replacing 'double' with 'long long'. The latter is supposed to be stored exactly, isn't it?
If you call a function taking double, it won't magically operate on long long instead. Your value is simply converted to double and you'll just get the same result.
Even with a function handling long long (which has 64 bits on nowadays' typical platforms), you can't deal with such large numbers. 64 bits aren't enough to store them. With an unsigned integer type, they will just "wrap around" to 0 on overflow. With a signed integer type, the behavior of overflow is undefined (but still somewhat likely a wrap around). So you'll get some number that has absolutely nothing to do with your expected result. That's arguably worse than the result with a floating point type, that's just not precise.
For exact calculations on large numbers, the only way is to store them in an array (typically of unsigned integers like uintmax_t) and implement all the arithmetics yourself. That's a nice exercise, and a lot of work, especially when performance is of interest (the "naive" arithmetic algorithms are typically very inefficient).
For some real-life program, you won't reinvent the wheel here, as there are libraries for handling large numbers. The arguably best known is libgmp. Read the manuals there and use it.

C weird approximation on floating point [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
I have the following code:
#include<stdio.h>
int main(int argc, char const *argv[])
{
float min, max, step;
min = -0.85, max = 0.85, step = 0.002;
int rank = 3, total = 4;
float step1 = min + (max - min) * rank / total; // should be 0.425
printf("%f %.7g\n", step1, step1); // 0.425000 0.4250001
float step2 = min + (max - min) * (rank + 1) / total - step; //should be 0.848
printf("%f %.7g\n", step2, step2); // 0.848000 0.848
float noc = (step2 - step1 + step) / step; //should be 212,5
printf("%f %.7g\n", noc, noc); // 212.499985 212.5
int nol = 1200;
int result = (int)nol * noc; //should be 255000
printf("%d\n", result); // 254999
return 0;
}
This is a fragment of code isolated from a project I have to do. The final result should be 255000, but for some causes, it shows 254999. Can someone please explain me what happens in the process? I have read somewhere that multiplying a floating number with 10^k and then dividing back solves such problems, but in this case, due to the variable step varying from 0.000001 to 0.1, I can't actually use that (in the same way, I can't use a defined EPSILON). What else can I do?
Thanks in advance!
P.S.: I have used double and long double as well, but with same problems, only this time error propagates from a further decimal. I am using gcc 4.8.2, under Ubuntu 14.04.1.
Truncation vs. rounding.
Due to subtle rounding effect of FP arithmetic, the product nol * noc may be slightly less than an integer value. Conversion to int results in fractional truncation. Suggest rounding before conversion to int.
#include <math.h>
int result = (int) roundf(nol * noc);
the significant problem(s) are:
1) mixing floating point and double with integer math
--so the compiler promotes all the math to float (or double)
2) not all numbers can be expressed exactly in float
3) --the initialization of min, max, step are taking double literals
and converting them to float
--even double cannot express all values exactly
--some precision is lost when performing the conversion from double to float
4) this code excerpt: (rank + 1) / total is always = 1
--(although the many conversions may result in being 'not exactly' 1)
5) argc and argv are not referenced in your code.
--this, given that all warnings are enabled, will rise two warnings
at compile time about unused parameters
6) this line in your code is not correct syntax
--(although the compiler might not complain) #include<stdio.h>
--it should be #include <stdio.h>
--sometimes spaces count, sometimes they dont

What's the first double that deviates from its corresponding long by delta?

I want to know the first double from 0d upwards that deviates by the long of the "same value" by some delta, say 1e-8. I'm failing here though. I'm trying to do this in C although I usually use managed languages, just in case. Please help.
#include <stdio.h>
#include <limits.h>
#define DELTA 1e-8
int main() {
double d = 0; // checked, the literal is fine
long i;
for (i = 0L; i < LONG_MAX; i++) {
d=i; // gcc does the cast right, i checked
if (d-i > DELTA || d-i < -DELTA) {
printf("%f", d);
break;
}
}
}
I'm guessing that the issue is that d-i casts i to double and therefore d==i and then the difference is always 0. How else can I detect this properly -- I'd prefer fun C casting over comparing strings, which would take forever.
ANSWER: is exactly as we expected. 2^53+1 = 9007199254740993 is the first point of difference according to standard C/UNIX/POSIX tools. Thanks much to pax for his program. And I guess mathematics wins again.
Doubles in IEE754 have a precision of 52 bits which means they can store numbers accurately up to (at least) 251.
If your longs are 32-bit, they will only have the (positive) range 0 to 231 so there is no 32-bit long that cannot be represented exactly as a double. For a 64-bit long, it will be (roughly) 252 so I'd be starting around there, not at zero.
You can use the following program to detect where the failures start to occur. An earlier version I had relied on the fact that the last digit in a number that continuously doubles follows the sequence {2,4,8,6}. However, I opted eventually to use a known trusted tool (bc) for checking the whole number, not just the last digit.
Keep in mind that this may be affected by the actions of sprintf() rather than the real accuracy of doubles (I don't think so personally since it had no troubles with certain numbers up to 2143).
This is the program:
#include <stdio.h>
#include <string.h>
int main() {
FILE *fin;
double d = 1.0; // 2^n-1 to avoid exact powers of 2.
int i = 1;
char ds[1000];
char tst[1000];
// Loop forever, rely on break to finish.
while (1) {
// Get C version of the double.
sprintf (ds, "%.0f", d);
// Get bc version of the double.
sprintf (tst, "echo '2^%d - 1' | bc >tmpfile", i);
system(tst);
fin = fopen ("tmpfile", "r");
fgets (tst, sizeof (tst), fin);
fclose (fin);
tst[strlen (tst) - 1] = '\0';
// Check them.
if (strcmp (ds, tst) != 0) {
printf( "2^%d - 1 <-- bc failure\n", i);
printf( " got [%s]\n", ds);
printf( " expected [%s]\n", tst);
break;
}
// Output for status then move to next.
printf( "2^%d - 1 = %s\n", i, ds);
d = (d + 1) * 2 - 1; // Again, 2^n - 1.
i++;
}
}
This keeps going until:
2^51 - 1 = 2251799813685247
2^52 - 1 = 4503599627370495
2^53 - 1 = 9007199254740991
2^54 - 1 <-- bc failure
got [18014398509481984]
expected [18014398509481983]
which is about where I expected it to fail.
As an aside, I originally used numbers of the form 2n but that got me up to:
2^136 = 87112285931760246646623899502532662132736
2^137 = 174224571863520493293247799005065324265472
2^138 = 348449143727040986586495598010130648530944
2^139 = 696898287454081973172991196020261297061888
2^140 = 1393796574908163946345982392040522594123776
2^141 = 2787593149816327892691964784081045188247552
2^142 = 5575186299632655785383929568162090376495104
2^143 <-- bc failure
got [11150372599265311570767859136324180752990210]
expected [11150372599265311570767859136324180752990208]
with the size of a double being 8 bytes (checked with sizeof). It turned out these numbers were of the binary form "1000..." which can be represented for far longer with doubles. That's when I switched to using 2n-1 to get a better bit pattern: all one bits.
The first long to be 'wrong' when cast to a double will not be off by 1e-8, it will be off by 1. As long as the double can fit the long in its significand, it will represent it accurately.
I forget exactly how many bits a double has for precision vs offset, but that would tell you the max size it could represent. The first long to be wrong should have the binary form 10000..., so you can find it much quicker by starting at 1 and left-shifting.
Wikipedia says 52 bits in the significand, not counting the implicit starting 1. That should mean the first long to be cast to a different value is 2^53.
Although I'm hesitant to mention Fortran 95 and successors in this discussion, I'll mention that Fortran since the 1990 standard has offered a SPACING intrinsic function which tells you what the difference between representable REALs are about a given REAL. You could do a binary search on this, stopping when SPACING(X) > DELTA. For compilers that use the same floating point model as the one you are interested in (likely to be the IEEE754 standard), you should get the same results.
Off hand, I thought that doubles could represent all integers (within their bounds) exactly.
If that is not the case, then you're going to want to cast both i and d to something with MORE precision than either of them. Perhaps a long double will work.

Resources