Error working with doubles and fmod - c

Im trying to calculate a power and then a module of big numbers (type double). I want to calcule (1234^79) mod 3337. The result is 901 (Ubuntu's calculator) but function fmod returns 1788.
#include <math.h>
#include <tgmath.h>
#include <stdlib.h>
#include <stdio.h>
void main(){
double res1;
double dou = powl(1234.00,79.00);//function for doubles
printf("Result in double o powl %.3f\n",dou);
res1=fmod(dou, 3337.00);//doubles
printf("Result in double of fmod %.2f\n",res1);
}
What am I doing wrong? Some answer?
Thanks in advance.

1234^79 has 245 decimal digits.
double only has a precision of around 17 decimal digits.
You need to use a little math to reduce this problem to something that doesn't require arbitrary precision (see Modular Exponentiation).
(Or just use an arbitrary precision math library + brute force if you aren't interested in an efficient solution.)

Related

Pow function returning wrong result

When I use the pow() function, sometimes the results are off by one. For example, this code produces 124, but I know that 5³ should be 125.
#include<stdio.h>
#include<math.h>
int main(){
int i = pow(5, 3);
printf("%d", i);
}
Why is the result wrong?
Your problem is that you are mixing integer variables with floating point math. My bet is that the result of 5^3 is something like 124.999999 due to rounding problems and when cast into integer variable get floored to 124.
There are 3 ways to deal with this:
more safely mix floating math and integers
int x=5,y=3,z;
z=floor(pow(x,y)+0.5);
// or
z=round(pow(x,y));
but using this will always present a possible risk of rounding errors affecting the result especially for higher exponents.
compute on floating variables only
so replace int with float or double. This is a bit safer than #1 but still in some cases is this not usable (depends on the task). and may need occasional floor,ceil,round along the way to get the wanted result correctly.
Use integer math only
This is the safest way (unless you cross the int limit). The pow can be computed on integer math relatively easily see:
Power by squaring for negative exponents
pow(x, y) is most likely implemented as exp(y * log(x)): modern CPUs can evaluate exp and log in a couple of flicks of the wrist.
Although adequate for many scientific applications, when truncating the result to an integer, the result can be off for even trivial arguments. That's what is happening here.
Your best bet is to roll your own version of pow for integer arguments; i.e. find one from a good library. As a starting point, see The most efficient way to implement an integer based power function pow(int, int)
Use Float Data Type
#include <stdio.h>
#include <math.h>
int main()
{
float x=2;
float y=2;
float p= pow(x,y);
printf("%f",p);
return 0;
}
You can use this function instead of pow:
long long int Pow(long long int base, unsigned int exp)
{
if (exp > 0)
return base * Pow(base, exp-1);
return 1;
}

How can I conver string to double value in c?

I want to get the equivalent double number of any word.
I use atof, but it give me zero output.
How can I solve it
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("%f\n", *(double*)"hello");
}
That's because you did not read the documentation of atof(), or strtod()
https://www.tutorialspoint.com/c_standard_library/c_function_strtod.htm
http://www.cplusplus.com/reference/cstdlib/strtod/
Doubles are floating point numbers, essentially non-integer numbers.
"hello" is not a valid string representation of a double. Try a number instead, for example
printf("%f\n", atof("3.141"));

Why does casting to int not floor all doubles in C

Given the C code:
#include <math.h>
#include <stdio.h>
int main(){
int i;
double f=log(2.0)/log(pow(2.0,1.0/2.0));
printf("double=%f\n",f);
printf("int=%d\n",(int) f);
}
I get the output:
double=2.000000
int=1
f is apparently at least 2.0. Why is the cast value not 2?
Because the value of the double was less than 2
double=1.99999999999999978
int=1
Try it but this time add some precision
#include <math.h>
#include <stdio.h>
int main(){
int i;
double f=log(2.0)/log(pow(2.0,1.0/2.0));
printf("double=%0.17f\n",f);
printf("int=%d\n",(int) f);
}
Confusing as hell the first time you experience it. Now, if you try this
#include <math.h>
#include <stdio.h>
int main(){
int i;
double f=log(2.0)/log(pow(2.0,1.0/2.0));
printf("double=%0.17f\n",f);
printf("int=%d\n",(int) f);
printf("int=%d\n", (int)round(f));
}
It will correctly round the value. If you look in the man page (on a mac at least) you'll see the following comment...
round, lround, llround -- round to integral value, regardless of rounding direction
What do they mean by direction, it's all specified in IEEE 754. If you check the different ways to round to an integer... floor is mentioned as rounding towards -ve infinity which is in this case was towards 1 :)
Floating point types are unable to represent some numbers exactly. Even though mathematically, the calculation should be exactly 2, with IEEE754 floating points, the result turns out to be slightly less than 2. For more information see this question.
If you increase the precision of your output by specifying %.20f instead of just %f, you will see that the number is not exactly 2, and that when printing with less accuracy, the result is simply rounded.
When converting to an int however, the full accuracy of the floating point type is used, and since it comes to just under 2, the result when converting to an integer is 1.
Integer does not take a rounded up value but makes a truncation. So, if f is equal to 1.999999999999[..]9, the int value will be 1.
Also, as the double wants to be the more accurate possible, he will take a rounded up value considering the number of characters he can show, which is 2.000000.

don't getting correct volume of a sphere from my C code?

I have just started learning c programming.I have a question.
I wanna calculate the volume of a sphere from radius.my code is:
but it is not giving me correct ans for 1523.result is 14797486080.000
but the correct ans will be 14797486501.627.Where is the problem?
I found the problem here https://www.urionlinejudge.com.br/judge/en/problems/view/1011
Your computation is performed in double and converted on assignment to float, so you loose precision. You probably just should declare q as double.
Also if you are really concerned about precision, you should use a better approximation of π.
If you want better precision in the result, try double instead of float. A 32 bit float will give you a precision of about 7 digits. A 64 bit double will give you a precision of about 15 digits.
You probably just should declare q as double. you should use a better approximation of π.
Try using this:
#include <stdio.h>
#include <math.h>
int main()
{
int a;
double volume;
printf("Enter the radius of a sphere: ");
scanf("%d", &a);
volume=(4.0/3) *3.14159*pow(a,3);
printf("Volume of a sphere is: %3f", volume);
return 0;
}

sin, cos, tan and rounding error

I'm doing some trigonometry calculations in C/C++ and am running into problems with rounding errors. For example, on my Linux system:
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[]) {
printf("%e\n", sin(M_PI));
return 0;
}
This program gives the following output:
1.224647e-16
when the correct answer is of course 0.
How much rounding error can I expect when using trig functions? How can I best handle that error? I'm familiar with the Units in Last Place technique for comparing floating point numbers, from Bruce Dawson's Comparing Floating Point Numbers, but that doesn't seem to work here, since 0 and 1.22e-16 are quite a few ULPs apart.
The answer is only 0 for sin(pi) - did you include all the digits of Pi ?
-Has anyone else noticed a distinct lack of, irony/sense of humour around here?
An IEEE double stores 52 bits of mantissa, with the "implicit leading
one" forming a 53 bit number. An error in the bottom bit of a result
therefore makes up about 1/2^53 of the scale of the numbers. Your output is
of the same order as 1.0, so that comes out to just about exactly one
part in 10^16 (because 53*log(2)/log(10) == 15.9).
So yes. This is about the limit of the precision you can expect. I'm
not sure what the ULP technique you're using is, but I suspect you're
applying it wrong.
Sine of π is 0.0.
Sine of M_PI is about 1.224647e-16.
M_PI is not π.
program gives ... 1.224647e-16 when the correct answer is of course 0.
Code gave a correct answer to 7 significant places.
The following does not print the sine of π. It prints the sine of a number close to π. See below pic.
π // 3.141592653589793 2384626433832795...
printf("%.21\n", M_PI); // 3.141592653589793 115998
printf("%.21f\n", sin(M_PI));// 0.000000000000000 122465
Note: With the math function sine(x), the slope of the curve is -1.0 at x = π. The difference of π and M_PI is about the sin(M_PI) - as expected.
am running into problems with rounding errors
The rounding problem occurs when using M_PI to represent π. M_PI is the double constant closest to π, yet since π is irrational and all finite double are rational, they must differ - even by a small amount. So not a direct rounding issue with sin(), cos(), tan(). sin(M_PI) simple exposed the issue started with using M_PI - an inexact π.
This problem, with different non-zero results of sin(M_PI), occurs if code used a different FP type like float, long double or double with something other than 53 binary bits of precision. This is not a precision issue so much as a irrational/rational one.
#Josh Kelley - ok serious answer.
In general you should never compare the results of any operation involving floats or doubles with each other.
The only exceptions is assignment.
float a=10.0;
float b=10.0;
then a==b
Otherwise you always have to write some function like bool IsClose(float a,float b, float error) to allow you to check if two numbers are within 'error' of each other.
Remember to also check signs/use fabs - you could have -1.224647e-16
There are two sources of error. The sin() function and the approximated value of M_PI. Even if the sin() function were 'perfect', it would not return zero unless the value of M_PI were also perfect - which it is not.
I rather think that will be system-dependent. I don't think the Standard has anything to say on how accurate the transcendental functions will be. Unfortunately, I don't remember seeing any discussion of function precision, so you'll probably have to figure it out yourself.
Unless your program requires significant digits out to the 16th decimal place or more, you probably can do the rounding manually. From my experience programming games we always rounded our decimals to a tolerable significant digit. For example:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define HALF 0.5
#define GREATER_EQUAL_HALF(X) (X) >= HALF
double const M_PI = 2 * acos(0.0);
double round(double val, unsigned places = 1)
{
val = val * pow(10.0f, (float)places);
long longval = (long)val;
if ( GREATER_EQUAL_HALF(val - longval) ) {
return ceil(val) / pow(10.0f, (float)places);
} else {
return floor(val) / pow(10.0f, (float)places);
}
}
int main()
{
printf("\nValue %lf", round(sin(M_PI), 10));
return 0;
}
I get the exact same result on my system - I'd say it is close enough
I would solve the problem by changing the format string to "%f\n" :)
However, this gives you a "better" result, or at least on my system it does give -3.661369e-245
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[]) {
printf("%e\n", (long double)sin(M_PI));
return 0;
}
Maybe too low accuracy of implementation
M_PI = 3.14159265358979323846 (M_PI is not π)
http://fresh2refresh.com/c/c-function/c-math-h-library-functions/
It is an inaccuracy in implementation, see Stephen C. Steel's comment under Andy Ross` answer above and chux's answer.

Resources