Beginner here.
Why is this an endless loop ?
for (p = 0; p < 5; p += 0.5)
{
printf("p=%2.2f\n",p);
}
You see an endless loop because your p is of an integral type (e.g. an int). No matter how many times you add 0.5 to an int, it would remain 0, because int truncates double/fp values assigned to it. In other words, it is equivalent to a loop where you add zero on each step.
If you make p a float or a double, your problem would go away.
EDIT (Suggested by Oli Charlesworth's comment)
It is worth noting that using floats and doubles to control loops is discouraged, because the results are not always as clean as in your example. Changing the step from 0.5 (which is 2 to the negative power of 1) to 0.1 (which is not an integral negative power of 2) would change the results that you see in a rather unexpected way.
If you need to iterate by a non-integer step, you should consider using this simple pattern:
// Loop is controlled by an integer counter
for (int i = 0 ; i != 10 ; i++) {
// FP value is calculated by multiplying the counter by the intended step:
double p = i * 0.5;
// p is between 0 and 4.5, inclusive
}
I think it depends on how p is declared. If it's an integer type, p will always be 0 (because the result of 0 + 0.5 will be truncated to 0 every time) so the for will never stop.
a type conversion problem, float/double lost precision when assigned to an integer type.
P.S. It is really a very bad idea to use float/double in condition test. Not all floating point numbers in computers are accurate.
If p is a float or a double, there's nothing wrong with the code, and the loop will terminate.
If p is integer, the behaviour of the code is undefined since the format specifier in printf() is wrong.
when you add a double constant to integer variable, the double constant "becomes" integer. 0.5 becomes just 0. So you add 0 to p.
Related
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;
}
I saw this code on Exam: the question is how many times this string will be printed.
I thought first it will be 10 times but this is wrong.
Can someone tell me why my answer is wrong.
This is part of a code in the C language.
for (float x = 100000001.0f; x <= 100000010.0f; x += 1.0f) {
printf("lbc");
}
Assuming x is a 32 bit floating point:
Floating point values have a limited resolution. 100000001 is 1*10^8 so you lose your 1 at the end. If you would add 1, it again gets lost because the next float value is 1.00000008*10^8. You can add as many 1s as you like the result will always be the same.
That is the reason why your code is an endless loop.
float x = 100000001.0f;
will initialize x with the nearest representable float, which is 100000000. Adding 1 to this value will lead to the same value.
If you print the value of x in the loop you will see what happen: http://ideone.com/3FJGTz
As part of a program that I am writing for an assignment, I need to compare two numbers. Essentially, the program computes the eccentricity of an ellipse given its two axes and it has to compare the value of the calculated eccentricity to the (given) eccentricity of the Moon's orbit around the Earth, and Earth's orbit around the Sun. If the calculated eccentricity is greater than the given eccentricity, then this needs to be represented by a value of 1, otherwise, a value of 0. All of these values are floating-point, specifically, long double.
The constraints of the assignment do not allow me to use comparison operators (like >) or any sort of logic (!x or if-else). However, I am allowed to use the pow and sqrt functions from the math.h library. I am also allowed to use arithmetic operations as well as the modulo operation.
I know that I can take advantage of integer division to truncate the decimal if the denominator is greater than the numerator, i.e.:
int x = eccentricity / MOON_ORBIT_ECCENTRICITY;
... will be 0 if MOON_ORBIT_ECCENTRICITY is greater than eccentricity. However, if this relationship is inverted, then the value of x could be any non-zero integer. In such a case, the desired result is 1.
The first and most intuitive (and naïve) solution was:
int y = (x / x);
This will return 1 if x is non-zero. However, if x is 0, then my program crashes due to division by zero. In fact, I keep running into the problem of dividing by zero. This also happens in the case of:
int y = (x + 1) % x;
Does anyone have an idea of how to solve this? This seems so frustratingly easy.
#lurker comment above is a good approach to handle eccentricity as restricted by OP.
So as not to copy that, consider the not-so-serious following:
// Return e1 > e2
int Eccentricity_Compare(long double e1, long double e2) {
char buf[20];
// print a number beginning with
// if e2 >= e1: `+`
// else `-`
sprintf(buf, "%+Le", e2 - e1); // reverse subtraction for = case
const char *pm = "+-";
char *p = strchr(pm, buf[0]);
return (int) (p - pm);
}
Wink, wink: OP said nothing about <stdio.h> functions.
I have a program here that is supposed to sum up the series
1+1/2+1/3+1/4... etc
The only user entry is to enter how many times you want this sum to run for.
However, I keep getting the sum one.
#include <stdio.h>
int main(void)
{
int b,x; /* b is number of times program runs and x is the count*/
float sum;
printf("Enter the number of times you want series to run.\n");
scanf("%d", &b);
printf("x sum\n");
for(x=1,sum=0;x<b+1;x++)
{
printf("%d %9.3f\n",x, (sum +=(float)(1/x)));
}
return 0;
}
I don't quite get why it isn't working. As you can see, I did tell it to print x and when it did, x was incrementing correctly.The sum just kept adding up to one.
You have misplaced parentheses so you're doing integer division for 1/x and getting 0 for any value of x > 1.
I suggest you change:
printf("%d %9.3f\n",x, (sum +=(float)(1/x)));
to:
printf("%d %9.3f\n",x, (sum += 1.0f/x));
Two problems: one dull, one interesting.
1) 1 / x will be imprecise since 1 and x are both integral types and so the computation will be done in integer arithmetic. All the cast does is convert the resultant integral type to floating point. To resolve this, write 1.0 / x. Then 'x' is promoted to floating point prior to the division.
2) You should reverse the order of the for loop:
sum = 0.0;
for(x = b; x >= 1; --x)
(I've also moved the initialisation or sum from the for loop as sum = 0 is an expression of type float but x = b is an expression of type int so you ought not use the comma operator as they have different data types.)
The reason is subtle: you should only add floating points of similar magnitude. Doing the loop my way means the smaller values are added first.
The effect will be noticeable for high values of b; try it. Your original way will always understate the sum.
The problem is integer division when you do 1/x, which always result in 0 as long as x is greater than 1. Even it you later convert this to a float, the "damage" is already done. An easy fix would be to change the division to 1.0f/x.
Since you have declared x as an int, (1/x) returns 1 when x is 1 and 0 for x>1. So, sum remains 1. So you get the same result.
So, change (1/x) to 1.0f/x, so that the result is returned as a float
Here you are computing 1/x in which the fractional value is truncated. Converting it into float after the original value has been truncated doesn't make sense.
So change this to:-
printf("%d %9.3f\n",x, (sum +=(float)(1/x)));
to
printf("%d %9.3f\n",x, (sum += 1.0f/x));
The expression (1/x) will always be integer division. For the first run this will be 1/1 giving you 1. However, next time round it will be 1/2 which is 0. Basically for 1/x where x>1 the answer will be zero.
To get around this write the expression as 1.0/x which will cause x to be promoted to a double, giving you double division.
I edited a C program for my assignment, previously there wasn't typecasting and the iteration stopped at i=1, now with the typecasting it stops at i=6.
Any ideas why? Thanks in advance!
int main(void)
{
int i = 0;
double d = 0.0;
while ( (i == (int) (d * 10)) && (i < 10) )
{
i = i + 1;
d = (double) (d + 0.1);
printf("%d %lf\n", i, d);
}
printf("%d %lf\n", i, d);
getch();
return 0;
}
Floating point arithmetic is inexact. The value 0.1 is not exactly representable in binary floating point. The recommended reading here is: What Every Computer Scientist Should Know About Floating-Point Arithmetic.
At some point in the program, d becomes slightly less than i/10 due to rounding error, and so your loop terminates.
In addition to the other answers, I'd like to answer the question why the loop terminates earlier with the condition i == (d * 10) than with i == (int) (d * 10).
In the first case, int value at the left side of == is promoted to double, so the inequality happens when the accumulated error in d*10 is either positive or negative (e.g. 0.999999 or 1.000001).
In the 2nd case, the right side is truncated to int, so the inequality happens only when the error is negative (e.g. 5.999999). Therefore, the 1st version would fail earlier.
As has been stated many times before, the reason this doesn't work is that binary floating point numbers cannot represent all decimal floating point binary numbers, it just isn't possible. To read more, check out this really great article:
What Every Programmer Should Know About Floating-Point Arithmetic
Now, on the more practical side of things, when using floating point and comparing it to another number, you should almost always round the value or use an epsilon value, like this:
if (ABS(doubleValue - intValue) < 0.00001) // 0.00001 is a margin-of-error for floating point arithmetic
// the two numbers are even (or close to it)