I have this question:
We claim that it is unsafe to use equality testing with floating point numbers because the arithmetic operations introduce rounding errors which mean that two numbers which ought to be equal are not.
For this program, you should pick a number N, and write a program to show for which of the integers x between 1 and 1000 the equality
(x+1)/N = (x/N) + (1/N) fails
#include <stdio.h>
int main () {
int x;
float N = 50;
for (x=0; x<1001; x++) {
if ((x+1)/N != (x/N) + (1/N))
{
printf("%i\n",x);
}
}
}
Is this correct?
Thanks.
Your program is wrong. It should start with x=1 instead of x=0.
But beside that, you should pick two examples (one that has been printed by the program and one that hasn’t) and calculate them by hand. With just pen and paper and the IEEE 754-1985 rules. Then print both sides of the equation and compare them to your hand-computed results.
Related
I was recently asked this question in a programming test. I can't seem to understand why I am getting the answer '1'. I am a beginner in the C programming language.
Here is my code:
#include<stdio.h>
int main()
{
float c = 0;
int n, i = 1;
printf("Enter the number here: ");
n = getchar();
while (i <= 2*n - 1)
{
c = c + (1/i);
i = i + 2;
}
printf("%f", c);
}
I have already tried using a for loop, but the answer remains the same. Any help would be appreciated!
The problem in your code lies on this line:
c = c + (1/i);
Here, the operation performed inside the parentheses is integer division! So, when i has any value greater than 1, the result will be zero. This zero is then converted to a float value.
To force the compiler to use floating point division, use this:
c = c + (1.0/i);
I agree with Adrian's answer.
Another issue is because of the way floating point numbers are represented in a system when they are added in arbitrary order, precision can be lost.
To have maximum precision, floating point numbers should be added from smallest first to largest last.
As I am trying to compare these doubles, it won't seem to be working correctly
Here it goes: (This is exactly my problem)
#include <stdio.h>
#include <math.h>
int main () {
int i_wagen;
double dd[20];
dd[0]=0.;
dd[1]=0.;
double abstand= 15.;
double K_spiel=0.015;
double s_rel_0= K_spiel;
int i;
for(i=1; i<=9; i++)
{
i_wagen=2*(i-1)+2;
dd[i_wagen]=dd[i_wagen-1]-abstand;
i_wagen=2*(i-1)+3;
dd[i_wagen]=dd[i_wagen-1]-s_rel_0;
}
double s_rel=dd[3-1]-dd[3];
if((fabs(s_rel) - K_spiel) == 0.)
{
printf("yes\n");
}
return(0);
}
After executing the programm, it wont print the yes.
How to compare double variables in the if statement?
Take under account limited precision of the double representation of floating point numbers!
Your problem is simple and covered in Is floating point math broken?
Floating point operations are not precise. The representation of the given number may not be precise.
For 0.1 in the standard binary64 format, the representation can be written exactly as 0.1000000000000000055511151231257827021181583404541015625
Double precision (double) gives you only 52 bits of significant, 11 bits of exponent, and 1 sign bit. Floating point numbers in C use IEEE 754 encoding.
See the output of your program and the possible fix where you settle down for the variable being close to 0.0:
#include <stdio.h>
#include <math.h>
#define PRECISION 1e-6
int main (void) {
int i_wagen;
double dd[20];
dd[0]=0.;
dd[1]=0.;
double abstand= 15.;
double K_spiel=0.015;
double s_rel_0= K_spiel;
int i;
for(i=1; i<=9; i++)
{
i_wagen = 2*(i-1)+2;
dd[i_wagen] = dd[i_wagen-1]-abstand;
i_wagen = 2*(i-1)+3;
dd[i_wagen] = dd[i_wagen-1] - s_rel_0;
}
double s_rel = dd[3-1]-dd[3];
printf(" s_rel %.16f K_spiel %.16f diff %.16f \n" , s_rel, K_spiel, ((fabs(s_rel) - K_spiel)) );
if((fabs(s_rel) - K_spiel) == 0.0) // THIS WILL NOT WORK!
{
printf("yes\n");
}
// Settle down for being close enough to 0.0
if( fabs( (fabs(s_rel) - K_spiel)) < PRECISION)
{
printf("yes!!!\n");
}
return(0);
}
Output:
s_rel 0.0150000000000006 K_spiel 0.0150000000000000 diff 0.0000000000000006
yes!!!
You're comparing x to two different matrix entries: the first if compares x to coeff[0][0], the second to coeff[0][1]. So if x is greater than coeff[0][0] and less than or equal to coeff[0][1] the program will execture the final else branch. You probably want to compare x to the same matrix entry in both if statements. And in that case, the last else branch would be useless, since one of the three cases (less than, equal to or greater than) MUST be true.
First, dd[i_wagen-1] as used in the statement:
dd[i_wagen]=dd[i_wagen-1]-abstand;
is uninitialized. Code will run, but will have unpredictable results.
To initialize, you can use:
double dd[20]={0}; //sufficient
or possibly
double dd[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //explicit, but not necessary
Moving to your actual question, it all comes down to this statement:
if((fabs(s_rel) - K_spiel) == 0.)
You have initialized K_spiel to 0.015. And at this point in your execution flow s_rel appears to be close to 0.015. But it is actually closer to 0.0150000000000006. So the comparison fails.
One trick that is commonly used is to define an epsilon value, and use it to determine if the difference between two floating point values is small enough to satisfy your purpose:
From The Art of Computer Programming, the following snippet uses this approach, and will work for your very specific example: (caution: Read why this approach will not work for all floating point related comparisons.)
bool approximatelyEqual(float a, float b, float epsilon)
{
return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
}
So replace the line:
if((fabs(s_rel) - K_spiel) == 0.)
with
if(approximatelyEqual(s_rel, K_spiel, 1e-8)
Given this code that my professor gave us in an exam which means we cannot modify the code nor use function from other libraries (except stdio.h):
float x;
(suppose x NOT having an integer part)
while (CONDITION){
x = x*10
}
I have to find the condition that makes sure that x has no valid number to the right of decimal point not giving attention to the problems of precision of a float number (After the decimal point we have to have only zeros). I tried this condition:
while ((fmod((x*10),10))){
X = X*10
}
printf(" %f ",x);
example:
INPUT x=0.456; --------> OUTPUT: 456.000
INPUT X=0.4567;--------> OUTPUT; 4567.000
It is important to be sure that after the decimal point we don't have any
significant number
But I had to include math.h library BUT my professor doesn't allow us to use it in this specific case (I'm not even allowed to use (long) since we never seen it in class).
So what is the condition that solve the problem properly without this library?
As pointed out here previously:Due to the accuracy of floats this is not really possible but I think your Prof wants to get something like
while (x - (int)x != 0 )
or
while (x - (int)x >= 0.00000001 )
You can get rid of the zeroes by using the g modifier instead of f:
printf(" %g \n",x);
There is fuzziness ("not giving attention to the problems of precision of a float number") in the question, yet I think a sought answer is below, assign x to an integer type until x no longer has a fractional part.
Success of this method depends on INT_MIN <= x <= INT_MAX. This is expected when the number of bits in the significant of float does not exceed the value bits of int. Although this is common, it is not specified by C. As an alternative, code could with a wider integer type like long long with a far less chance of the range restriction issue.
Given the rounding introduced with *10, this method is not a good foundation of float to text conversion.
float Dipok(float x) {
int i;
while ((i=x) != x) {
x = x*10;
}
return x;
}
#include <assert.h>
#include <stdio.h>
#include <float.h>
void Dipok_test(float x) {
// suppose x NOT having an integer part
assert(x > -1.0 && x < 1.0);
float y = Dipok(x);
printf("x:%.*f y:%.f\n", FLT_DECIMAL_DIG, x, y);
}
int main(void) {
Dipok_test(0.456);
Dipok_test(0.4567);
return 0;
}
Output
x:0.456000000 y:456
x:0.456699997 y:4567
As already pointed out by 2501, this is just not possible.
Floats are not accurate. Depending on your platform, the float value for 0.001 is represented as something like 0.0010000001 in fact.
What would you expect the code to calculate: 10000001 or 1?
Any solution will work for some values only.
I try to answer to my exam question please if I say something wrong correct me!
It is not possible to find a proper condition that makes sure that there are no valid number after the decimal point. For example : We want to know the result of 0.4*20 which is 8.000 BUT due to imprecision problems the output will be different:
f=0.4;
for(i=1;i<20;i++)
f=f+0.4;
printf("The number f=0.4*20 is ");
if(f!=8.0) {printf(" not ");}
printf(" %f ",8.0);
printf("The real answer is f=0.4*20= %f",f);
Our OUTPUT will be:
The number f=0.4*20 is not 8.000000
The real answer is f=0.4*20= 8.000001
This is the code which I have written to find approx square root a non perfect number(in the order 0.0001 and also exact square root of a perfect square. It is working with non perfect square numbers but not perfect. When I put 25 it gives 5.000068
#include<stdio.h>
int main()
{
float a,i,count;
scanf("%f",&a);
for(count=1;(1);count=count+0.0001)
{
i=count*count;
if (i<=a)
break;
}
printf("%f",count);
return 0;
}
Your method is wrong for computing square roots.
You deserve a bad grade for not reading a bit about square roots. Understanding the problem is the first step for any software development.
First, you should read The Floating Point Guide and the classical What Every Programmer Should Know About Floating-Point Arithmetic. It explains why your program cannot work (i.e. gives inaccurate results).
Then, your program is very inefficient (for large input numbers like several billions, it takes an enormous amount of computing time; for very small numbers like 0.01 it probably never terminates). Learn about Newton-Raphson's method, perhaps by reading some basic math book.
Notice that many fixpoint computations translate to iterative algorithms.
There are two things that are faulty with your code:
Floating point is not exact. If you want more accuracy, use double, not float.
Your increment value is too large. If you incremented by a smaller amount you would (or should) get the desired value: See here: http://ideone.com/7XM2IK
The next issue doesn't affect your code now, but be warned anyway:
Do not use floating point arithmetic as a loop counter. To fix this issue, normalize your loop to do integer counts, and do the floating point inside the loop:
int count;
float dCount = 1.0;
float i, a;
//...
for (count=0; count < 100000; ++count)
{
//...
}
See this link: https://www.securecoding.cert.org/confluence/display/java/NUM09-J.+Do+not+use+floating-point+variables+as+loop+counters
If you dont want to struggle with books and math:
#include <stdio.h>
#include <math.h>
int main()
{
float n = 25;// ofc use scanf xD
n=sqrt(n);
printf("%.5f", n);
return 0;
}
I've got a program that calculates the approximation of an arcsin value based on Taylor's series.
My friend and I have come up with an algorithm which has been able to return the almost "right" values, but I don't think we've done it very crisply. Take a look:
double my_asin(double x)
{
double a = 0;
int i = 0;
double sum = 0;
a = x;
for(i = 1; i < 23500; i++)
{
sum += a;
a = next(a, x, i);
}
}
double next(double a, double x, int i)
{
return a*((my_pow(2*i-1, 2)) / ((2*i)*(2*i+1)*my_pow(x, 2)));
}
I checked if my_pow works correctly so there's no need for me to post it here as well. Basically I want the loop to end once the difference between the current and next term is more or equal to my EPSILON (0.00001), which is the precision I'm using when calculating a square root.
This is how I would like it to work:
while(my_abs(prev_term - next_term) >= EPSILON)
But the function double next is dependent on i, so I guess I'd have to increment it in the while statement too. Any ideas how I should go about doing this?
Example output for -1:
$ -1.5675516116e+00
Instead of:
$ -1.5707963268e+00
Thanks so much guys.
Issues with your code and question include:
Your image file showing the Taylor series for arcsin has two errors: There is a minus sign on the x5 term instead of a plus sign, and the power of x is shown as xn but should be x2n+1.
The x factor in the terms of the Taylor series for arcsin increases by x2 in each term, but your formula a*((my_pow(2*i-1, 2)) / ((2*i)*(2*i+1)*my_pow(x, 2))) divides by x2 in each term. This does not matter for the particular value -1 you ask about, but it will produce wrong results for other values, except 1.
You ask how to end the loop once the difference in terms is “more or equal to” your epsilon, but, for most values of x, you actually want less than (or, conversely, you want to continue, not end, while the difference is greater than or equal to, as you show in code).
The Taylor series is a poor way to evaluate functions because its error increases as you get farther from the point around which the series is centered. Most math library implementations of functions like this use a minimax series or something related to it.
Evaluating the series from low-order terms to high-order terms causes you to add larger values first, then smaller values later. Due to the nature of floating-point arithmetic, this means that accuracy from the smaller terms is lost, because it is “pushed out” of the width of the floating-point format by the larger values. This effect will limit how accurate any result can be.
Finally, to get directly to your question, the way you have structured the code, you directly update a, so you never have both the previous term and the next term at the same time. Instead, create another double b so that you have an object b for a previous term and an object a for the current term, as shown below.
Example:
double a = x, b, sum = a;
int i = 0;
do
{
b = a;
a = next(a, x, ++i);
sum += a;
} while (abs(b-a) > threshold);
using Taylor series for arcsin is extremly imprecise as the stuff converge very badly and there will be relatively big differencies to the real stuff for finite number of therms. Also using pow with integer exponents is not very precise and efficient.
However using arctan for this is OK
arcsin(x) = arctan(x/sqrt(1-(x*x)));
as its Taylor series converges OK on the <0.0,0.8> range all the other parts of the range can be computed through it (using trigonometric identities). So here my C++ implementation (from my arithmetics template):
T atan (const T &x) // = atan(x)
{
bool _shift=false;
bool _invert=false;
bool _negative=false;
T z,dz,x1,x2,a,b; int i;
x1=x; if (x1<0.0) { _negative=true; x1=-x1; }
if (x1>1.0) { _invert=true; x1=1.0/x1; }
if (x1>0.7) { _shift=true; b=::sqrt(3.0)/3.0; x1=(x1-b)/(1.0+(x1*b)); }
x2=x1*x1;
for (z=x1,a=x1,b=1,i=1;i<1000;i++) // if x1>0.8 convergence is slow
{
a*=x2; b+=2; dz=a/b; z-=dz;
a*=x2; b+=2; dz=a/b; z+=dz;
if (::abs(dz)<zero) break;
}
if (_shift) z+=pi/6.0;
if (_invert) z=0.5*pi-z;
if (_negative) z=-z;
return z;
}
T asin (const T &x) // = asin(x)
{
if (x<=-1.0) return -0.5*pi;
if (x>=+1.0) return +0.5*pi;
return ::atan(x/::sqrt(1.0-(x*x)));
}
Where T is any floating point type (float,double,...). As you can see you need sqrt(x), pi=3.141592653589793238462643383279502884197169399375105, zero=1e-20 and +,-,*,/ operations implemented. The zero constant is the target precision.
So just replace T with float/double and ignore the :: ...
so I guess I'd have to increment it in the while statement too
Yes, this might be a way. And what stops you?
int i=0;
while(condition){
//do something
i++;
}
Another way would be using the for condition:
for(i = 1; i < 23500 && my_abs(prev_term - next_term) >= EPSILON; i++)
Your formula is wrong. Here is the correct formula: http://scipp.ucsc.edu/~haber/ph116A/taylor11.pdf.
P.S. also note that your formula and your series are not correspond to each other.
You can use while like this:
while( std::abs(sum_prev - sum) < 1e-15 )
{
sum_prev = sum;
sum += a;
a = next(a, x, i);
}