my program reads data from that file :
6 150
0 1.75
30 0.8
60 0.5
70 1
120 0.1
140 0.9
and inserts those numbers(It starts from the second row) into an array of structs and then calculates the 'time'. The results are fine but one; the third one('time') is 100 but the output is 99.999992.
Here is the program :
#include <stdio.h>
#include <stdlib.h>
int di,i,k,m;
float vi,time;
int n;
int l;
struct node
{
int distance;
float velocity;
}DV[500000];
struct timeslist_node
{
struct timeslist_node *left;
int winner;
int loser;
double time;
struct timelist_node *right;
};
double calctime(int d,float v);
void print_array();
main()
{
FILE *fp;
fp=fopen("candidates.txt","r");
if (fp==NULL) exit(2);
fscanf(fp,"%d %d",&n,&l);
printf("%d,%d\n",n,l);
for(i=0;i<n;i++)
{
fscanf(fp,"%d %f",&DV[i].distance,&DV[i].velocity);
}
calctime(DV[i].distance,DV[i].velocity);
print_array();
fclose(fp);
system("pause");
}
double calctime(int d,float v)
{
for(i=0;i<n;i++)
{
if (i == 0)
{
{
if (DV[n-1].velocity==DV[i].velocity)
time=-1;
}
time=((l-DV[n-1].distance)/(DV[n-1].velocity-DV[i].velocity));
m=1;
k=n;
}
else
{
{ if (DV[i-1].velocity==DV[i].velocity)
time=-1;
}
time=((DV[i].distance-DV[i-1].distance)/(DV[i-1].velocity-DV[i].velocity));
k=i;
m=i+1;
}
printf ("t %d %d=%lf\n",m,k,time);
}
}
void print_array()
{
for(i=0;i<n;i++)
printf("D[%d],V[%d] = %d %.2f\n ",i,i,DV[i].distance,DV[i].velocity );
}
Thats happens because floating point numbers have a limited precision. If you want to know why, have a deeper look at how floating point are stored in the memory. http://en.m.wikipedia.org/wiki/Floating_point.
Typical float will handle math as expected, but only to within a certain range and precision.
That precision is typically about 6, maybe 7, significant digits. See FLT_DIG in <float.h>. 99.999992 is the results of printing a number to 8 significant digits. Using printf("%.5e", some_float) will limit the output to its realistic precision.
Using double rather than float will typically provide additional range and precision. But the same issues occur, albeit with more extreme numbers.
As many other have said, there are many issues contributing to the the fact that the sum was printed as 99.999992 rather than 100.0.
First, the sum is most likely precisely 99.99999237060546875, which is the previous float, assuming binary32, to 100.0. Printing a number like 99.99999237060546875 to 8 significant places is moving beyond reasonable precision expectations of float in C. "%f" prints a number with 6 digits following the decimal point. Since the number was 99.99999237060546875, a rounded number of 99.999992 with 2 + 6 significant digits was printed.
2nd: various math operations have inexact results. This is expected with 1.0/3.0, but it also happens with 100 + 0.1. This idea is outlined in the classic reference What Every Computer Scientist Should Know About Floating-Point Arithmetic
3rd, recall floating point numbers are not linearly, but logarithmically distributed. There are about as many numbers between 1.0 and 10.0 as between 10.0 and 100.0.
Can't you use Round for this?
Round(*STRING*);
Source: http://msdn.microsoft.com/en-us/library/75ks3aby(v=vs.110).aspx
Related
I'm trying to build a calculator, which input a number n it can automatically output the sum of
1/2+2/2 +1/3+2/3+3/3 +...+1/n+2/n+...+n/n and for each denominator, print the result once.
The calculator will restart and ask for input after output the final result of 1/2+2/2 +1/3+2/3+3/3 +...+1/n+2/n+...+n/n .And when the the user decides to stop the program enter 0.
for input=3 ,the output is sum =1 ,sum=2 ,yet I expected it to be sum=3/2, sum=7/2
Here's the program
#include <stdio.h>
int main(){
printf("Please enter the max denominator:\n");
int i,j,n;
int sum=0;
do{
scanf("%d",&n);
for (j=2;j<=n;j++){
for(i=1;i<=j;i++){
sum+= i/j;
if (i==j){
printf("sum=%d\n",sum);
break;
}
}
}
} while (n!=0);
return 0;
}
EDIT: revised part due to advice
int i,j,n;
double sum=0.0;
do{
scanf("%d",&n);
sum=0.0;
for (j=2;j<=n;j++){
for(i=1;i<=j;i++)
sum+=(double)i/j;
printf("sum=%lf\n",sum);
}
} while (n!=0);
return 0;
}
Your program is working with integers. i, j, n, and sum are all integers. This means they cannot encode numbers like 3/2 or 7/2.
So what happens when you divide two integers, like 1/2? The answer is that the result rounds down to the nearest integer. Since 1/2 is 0.5, the nearest integer below that is 0, so the result is 0.
You need to use float, which uses floating point arithmetic. Floating point arithmetic has its own set of fun rounding issues (You may be surprised to find that "0.2" cannot be represented exactly with floating point numbers).
A more exact alternative is to write your own functions to handle rational numbers as a pair of integers -- a numerator and a denominator. It will require additional algorithms (such as a Greatest Common Divisor algorithm), but it can describe these sorts of problems exactly.
float number = 123.8798831;
number=(floorf((number + number * 0.1) * 100.0)) / 100.0;
printf("number = %f",number);
I want to get number = 136.25
But the compiler shows me number = 136.259995
I know that I can write like this printf("number = %.2f",number) ,but I need the number itself for further operation.It is necessary that the number be stored in a variable as number = 136.25
It is necessary that the number be stored in a variable as number = 136.25
But that would be the incorrect result. The precise result of number + number * 0.1 is 136.26787141. When you round that downwards to 2 decimal places, the number that you would get is 136.26, and not 136.25.
However, there is no way to store 136.26 in a float because it simply isn't a representable value (on your system). Best you can get is a value that is very close to it. You have successfully produced a floating point number that is very close to 136.26. If you cannot accept the slight error in the value, then you shouldn't be using finite precision floating point arithmetic.
If you wish to print the value of a floating point number up to limited number of decimals, you must understand that not all values can be represented by floating point numbers, and that you must use %.2f to get desired output.
Round float to 2 decimal places in C language?
Just like you did:
multiply with 100
round
divide by 100
I agree with the other comments/answers that using floating point numbers for money is usually not a good idea, not all numbers can be stored exactly. Basically, when you use floating point numbers, you sacrifice exactness for being able to storage very large and very small numbers and being able to store decimals. You don't want to sacrifice exactness when dealing with real money, but I think this is a student project, and no actual money is being calculated, so I wrote the small program to show one way of doing this.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void)
{
double number, percent_interest, interest, result, rounded_result;
number = 123.8798831;
percent_interest = 0.1;
interest = (number * percent_interest)/100; //Calculate interest of interest_rate percent.
result = number + interest;
rounded_result = floor(result * 100) / 100;
printf("number=%f, percent_interest=%f, interest=%f, result=%f, rounded_result=%f\n", number, percent_interest, interest, result, rounded_result);
return EXIT_SUCCESS;
}
As you can see, I use double instead float, because double has more precession and floating point constants are of type double not float. The code in your question should give you a warning because in
float number = 123.8798831;
123.8798831 is of type double and has to be converted to float (possibly losing precession in the process).
You should also notice that my program calculates interest at .1% (like you say you want to do) unlike the code in your question which calculates interest at 10%. Your code multiplies by 0.1 which is 10/100 or 10%.
Here is an example of a function you can use for rounding to x number of decimals.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stddef.h>
double dround(double number, int dp)
{
int charsNeeded = 1 + snprintf(NULL, 0, "%.*f", dp, number);
char *buffer = malloc(charsNeeded);
snprintf(buffer, charsNeeded, "%.*f", dp, number);
double result = atof(buffer);
free(buffer);
return result;
}
int main()
{
float number = 37.777779;
number = dround(number,2);
printf("Number is %f\n",number);
return 0;
}
I am trying to write a program that outputs the number of the digits in the decimal portion of a given number (0.128).
I made the following program:
#include <stdio.h>
#include <math.h>
int main(){
float result = 0;
int count = 0;
int exp = 0;
for(exp = 0; int(1+result) % 10 != 0; exp++)
{
result = 0.128 * pow(10, exp);
count++;
}
printf("%d \n", count);
printf("%f \n", result);
return 0;
}
What I had in mind was that exp keeps being incremented until int(1+result) % 10 outputs 0. So for example when result = 0.128 * pow(10,4) = 1280, result mod 10 (int(1+result) % 10) will output 0 and the loop will stop.
I know that on a bigger scale this method is still inefficient since if result was a given input like 1.1208 the program would basically stop at one digit short of the desired value; however, I am trying to first find out the reason why I'm facing the current issue.
My Issue: The loop won't just stop at 1280; it keeps looping until its value reaches 128000000.000000.
Here is the output when I run the program:
10
128000000.000000
Apologies if my description is vague, any given help is very much appreciated.
I am trying to write a program that outputs the number of the digits in the decimal portion of a given number (0.128).
This task is basically impossible, because on a conventional (binary) machine the goal is not meaningful.
If I write
float f = 0.128;
printf("%f\n", f);
I see
0.128000
and I might conclude that 0.128 has three digits. (Never mind about the three 0's.)
But if I then write
printf("%.15f\n", f);
I see
0.128000006079674
Wait a minute! What's going on? Now how many digits does it have?
It's customary to say that floating-point numbers are "not accurate" or that they suffer from "roundoff error". But in fact, floating-point numbers are, in their own way, perfectly accurate — it's just that they're accurate in base two, not the base 10 we're used to thinking about.
The surprising fact is that most decimal (base 10) fractions do not exist as finite binary fractions. This is similar to the way that the number 1/3 does not even exist as a finite decimal fraction. You can approximate 1/3 as 0.333 or 0.3333333333 or 0.33333333333333333333, but without an infinite number of 3's it's only an approximation. Similarly, you can approximate 1/10 in base 2 as 0b0.00011 or 0b0.000110011 or 0b0.000110011001100110011001100110011, but without an infinite number of 0011's it, too, is only an approximation. (That last rendition, with 33 bits past the binary point, works out to about 0.0999999999767.)
And it's the same with most decimal fractions you can think of, including 0.128. So when I wrote
float f = 0.128;
what I actually got in f was the binary number 0b0.00100000110001001001101111, which in decimal is exactly 0.12800000607967376708984375.
Once a number has been stored as a float (or a double, for that matter) it is what it is: there is no way to rediscover that it was initially initialized from a "nice, round" decimal fraction like 0.128. And if you try to "count the number of decimal digits", and if your code does a really precise job, you're liable to get an answer of 26 (that is, corresponding to the digits "12800000607967376708984375"), not 3.
P.S. If you were working with computer hardware that implemented decimal floating point, this problem's goal would be meaningful, possible, and tractable. And implementations of decimal floating point do exist. But the ordinary float and double values any of is likely to use on any of today's common, mass-market computers are invariably going to be binary (specifically, conforming to IEEE-754).
P.P.S. Above I wrote, "what I actually got in f was the binary number 0b0.00100000110001001001101111". And if you count the number of significant bits there — 100000110001001001101111 — you get 24, which is no coincidence at all. You can read at single precision floating-point format that the significand portion of a float has 24 bits (with 23 explicitly stored), and here, you're seeing that in action.
float vs. code
A binary float cannot encode 0.128 exactly as it is not a dyadic rational.
Instead, it takes on a nearby value: 0.12800000607967376708984375. 26 digits.
Rounding errors
OP's approach incurs rounding errors in result = 0.128 * pow(10, exp);.
Extended math needed
The goal is difficult. Example: FLT_TRUE_MIN takes about 149 digits.
We could use double or long double to get us somewhat there.
Simply multiply the fraction by 10.0 in each step.
d *= 10.0; still incurs rounding errors, but less so than OP's approach.
#include <stdio.h>
#include <math.h> int main(){
int count = 0;
float f = 0.128f;
double d = f - trunc(f);
printf("%.30f\n", d);
while (d) {
d *= 10.0;
double ipart = trunc(d);
printf("%.0f", ipart);
d -= ipart;
count++;
}
printf("\n");
printf("%d \n", count);
return 0;
}
Output
0.128000006079673767089843750000
12800000607967376708984375
26
Usefulness
Typically, past FLT_DECMAL_DIG (9) or so significant decimal places, OP’s goal is usually not that useful.
As others have said, the number of decimal digits is meaningless when using binary floating-point.
But you also have a flawed termination condition. The loop test is (int)(1+result) % 10 != 0 meaning that it will stop whenever we reach an integer whose last digit is 9.
That means that 0.9, 0.99 and 0.9999 all give a result of 2.
We also lose precision by truncating the double value we start with by storing into a float.
The most useful thing we could do is terminate when the remaining fractional part is less than the precision of the type used.
Suggested working code:
#include <math.h>
#include <float.h>
#include <stdio.h>
int main(void)
{
double val = 0.128;
double prec = DBL_EPSILON;
double result;
int count = 0;
while (fabs(modf(val, &result)) > prec) {
++count;
val *= 10;
prec *= 10;
}
printf("%d digit(s): %0*.0f\n", count, count, result);
}
Results:
3 digit(s): 128
I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float isEven(int n)
{
return n % 2 == 0;
}
float isOdd(int n)
{
return !isEven(n);
}
float power(int x, int n)
{
// base case
if (n == 0)
{
return 1;
}
// recursive case: n is negative
else if (n < 0)
{
return (1 / power(x, -n));
}
// recursive case: n is odd
else if (isOdd(n))
{
return x * power(x, n-1);
}
// recursive case: n is positive and even
else if (isEven(n))
{
int y = power(x, n/2);
return y * y;
}
return true;
}
int displayPower(int x, int n)
{
printf("%d to the %d is %f", x, n, power(x, n));
return true;
}
int main(void)
{
int x = 0;
printf("What will be the base number?");
scanf("%d", &x);
int n = 0;
printf("What will be the exponent?");
scanf("%d", &n);
displayPower(x, n);
}
For example, here is a pair of inputs that works:
./exponentRecursion
What will be the base number?10
What will be the exponent?9
10 to the 9 is 1000000000.000000
But this is what I get for 10^10:
./exponentRecursion
What will be the base number?10
What will be the exponent?10
10 to the 10 is 1410065408.000000
Why does this write such a weird number?
BTW, 10^11 returns 14100654080.000000, exactly ten times the above.
Perhaps it may be that there is some "Limit" to the data type that I am using? I am not sure.
Your variable x is an int type. The most common internal representation of that is 32 bits. That a signed binary number, so only 31 bits are available for representing a magnitude, with the usual maximum positive int value being 2^31 - 1 = 2,147,483,647. Anything larger that that will overflow, giving a smaller magnitude and possibly a negative sign.
For a greater range, you can change the type of x to long long (usually 64 bits--about 18 digits) or double (usually 64 bits, with 51 bits of precision for about 15 digits).
(Warning: Many implementations use the same representation for int and long, so using long might not be an improvement.)
A float only has enough precision for about 7 decimal digits. Any number with more digits than that will only be an approximations.
If you switch to double you'll get about 16 digits of precision.
When you start handling large numbers with the basic data types in C, you can run into trouble.
Integral types have a limited range of values (such as 4x109 for a 32-bit unsigned integer). Floating point type haver a much larger range (though not infinite) but limited precision. For example, IEEE754 double precision can give you about 16 decimal digits of precision in the range +/-10308
To recover both of these aspects, you'll need to use a bignum library of some sort, such as MPIR.
If you are mixing different data types in a C program, there are several implicit casts done by the compiler. As there are strong rules how the compiler works one can exactly figure out, what happens to your program and why.
As I do not know all of this casting rules, I did the following: Estimating the maximum of precision needed for the biggest result. Then casting explicit every variable and funktion in the process to this precision, even if it is not necessary. Normally this will work like a workarount.
I was working on reading values in variables from a byte positioned file and I had to represent some value read into decimal with 6 digits representing fractional part, total no. of digits 20.
So the value could be for example be 99999999999999999999 (20 9s) and it is to be used as float considering the last six 9s representing fractional part.
Now when I was tring to do it with the method employed:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
char c[]="999999999.999999"; //9 nines to the left of decimal and 6 nines to the right
double d=0;
sscanf(c,"%lf",&d);
printf("%f\n",d);
return 0;
}
OUTPUT:999999999.999999 same as input
Now I increased the number of 9s to the left of decimal by 1 (making 10 nines to the left of decimal)
the output became 9999999999.999998.
On further increase of one more 9 to the left of decimal the outcome became rounded off to 100000000000.000000
For my usage it is possible that values with 14 digits to the left of decimal and 6 to the right of it can come in the variable - I want it to be converted precisely just like the input itself without and truncation or rounding off. Also I read somewhere that double can be used to represent a value with up to 16 significant digits but here when I used only 9999999999.999999 (10 nines to the left and 6 to the right) it produced outcome as 9999999999.999998 which contradicts this *represent a value with up to 16 significant digits` statement.
What should be done in this case?
The nature of floating point numbers is they are inaccurate. The bigger the number, the more inaccurate.
What should be done in this case?
You could try a long double, but even that's not guaranteed to be precise enough.
long double z = 99999999999999.999999L;
printf("%Lf\n", z); // 100000000000000.000000
You could store it as an integer and remember it's actually 1,000,000 times smaller. Unfortunately, 20 digits is a bit too large for even an unsigned 64 bit integer. It's 3 bits too large.
#include <inttypes.h>
int main() {
uint64_t x = 99999999999999999999ULL;
}
test.c:4:18: error: integer literal is too large to be represented in any integer type
uint64_t x = 99999999999999999999ULL;
You could make a struct that stores the pieces separately.
#include <inttypes.h>
#include <stdbool.h>
typedef struct {
bool positive;
uint64_t integer;
uint64_t decimal;
} bignum;
int main() {
bignum num = {
.positive = true,
.integer = 99999999999999,
.decimal = 999999
};
printf("%s" "%"PRIu64 "." "%"PRIu64 "\n",
num.positive ? "" : "-", num.integer, num.decimal
);
}
At which point you're building your own arbitrary-precision arithmetic library. Instead, use an existing one such as GMP. This can store numbers of any size. The trade off is speed and you have to use special types and functions.
#include <gmp.h>
int main() {
mpf_t y;
mpf_init_set_str(y, "99999999999999.999999", 10);
gmp_printf("%Ff\n", y);
}