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;
}
Related
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void)
{
const double TAX = 0.13;
double small = 17.96;
double subTotal = small * 6;
double taxes = subTotal * TAX;
printf("j SubTotal: %9.4lf Tax: %9.4lf \n", (double)subTotal, (double)taxes);
return 0;
}
The required output is
SubTotal: 107.7600 Tax: 14.0100 should come out.
My output is:
SubTotal: 107.7600 Tax: 14.0088
What should I do?
The solution is to not ever use floating point types for currency.
If you have a decimal type available, use it.
If you don't, write one.
Or, at a minimum, use long integers to store cents.
If you want to round to two decimal places, multiply by one hundred add one half, truncate to an int and then divide by one hundred. Like,
double round(double v) {
return ((int)(v * 100 + .5)) / 100.;
}
Then you can call that like
double taxes = round(subTotal * TAX);
And I get (with no other changes)
j SubTotal: 107.7600 Tax: 14.0100
C provides useful rounding functions rint(), round(), nearby(), llround() that well handle rounding corner cases.
To round to the nearest 100th, scale the value by /100.0, round and scale back.
#include <math.h>
double value = ...;
value *= 100.0;
value = round(value); // or rint(), nearby()
value /= 100.0;
At this point, value may not exactly be of the form ddd.dd but will be the closest double to that form. Printing with "%.4f" will then print to the closest 0.0001.
printf("%9.4lf\n", value);
Alternatively, take money and round to the smallest monetary unit - suppose OP wants to the nearest cent (0.01).
long long value_cents = llround(value * 100.0);
printf("%lld.%02d00", amount / 100, abs(amount % 100));
It’s a weird requirement to display four decimal places while rounding to two, but you can satisfy it by displaying two decimal places and hard-coding the characters 00 after it:
printf("j SubTotal: %9.2f00 Tax: %9.2f00 \n", subTotal, taxes);
Do not use floating point numbers for currency because they are tricky and inexact in many cases. Here is a working solution that gives you the exact output you want, but you should know it is strange to print more than two digits after the decimal point if those extra digits are always zero.
The + 99 in the code below is the trick you need to make the calculation always round up, instead of rounding down which is the normal behavior of unsigned integer division.
#include <stdio.h>
#include <stdint.h>
void print_money_with_strange_format(uint64_t amount)
{
printf("%llu.%02llu00", amount / 100, amount % 100);
}
int main(void)
{
uint64_t tax_rate = 13;
uint64_t small = 1796;
uint64_t subtotal = small * 6;
uint64_t tax = (subtotal * tax_rate + 99) / 100;
printf("SubTotal: ");
print_money_with_strange_format(subtotal);
printf(" Tax: ");
print_money_with_strange_format(tax);
printf("\n");
}
If you want to round the output to two decimals, but still producing four on output, just use
printf("%9.2f00", value);
and the value will be rounded to two decimals, and two zeros will be appended to it. But, why the computer should round 88 to 100 in a calculation, when you have not commanded it to round numbers at some place?
To round a number when the first decimal is over .5, you can just add 0.5 and then truncate the result. In case you want to do it at some position, just multiply the number by the required power of ten (in this case 100) and after the truncation, divide it again by that power(100), as proposed by other answers.
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 have come across some behaviour with the float type in C that I do not understand, and was hoping might be explained. Using the macros defined in float.h I can determine the maximum/minimum values that the datatype can store on the given hardware. However when performing a calculation that should not exceed these limits, I find that a typed float variable fails where a double succeeds.
The following is a minimal example, which compiles on my machine.
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
int main(int argc, char **argv)
{
int gridsize;
long gridsize3;
float *datagrid;
float sumval_f;
double sumval_d;
long i;
gridsize = 512;
gridsize3 = (long)gridsize*gridsize*gridsize;
datagrid = calloc(gridsize3, sizeof(float));
if(datagrid == NULL)
{
free(datagrid);
printf("Memory allocation failed\n");
exit(0);
}
for(i=0; i<gridsize3; i++)
{
datagrid[i] += 1.0;
}
sumval_f = 0.0;
sumval_d = 0.0;
for(i=0; i<gridsize3; i++)
{
sumval_f += datagrid[i];
sumval_d += (double)datagrid[i];
}
printf("\ngridsize3 = %e\n", (float)gridsize3);
printf("FLT_MIN = %e\n", FLT_MIN);
printf("FLT_MAX = %e\n", FLT_MAX);
printf("DBL_MIN = %e\n", DBL_MIN);
printf("DBL_MAX = %e\n", DBL_MAX);
printf("\nfloat sum = %f\n", sumval_f);
printf("double sum = %lf\n", sumval_d);
printf("sumval_d/sumval_f = %f\n\n", sumval_d/(double)sumval_f);
free(datagrid);
return(0);
}
Compiling with gcc I find the output:
gridsize3 = 1.342177e+08
FLT_MIN = 1.175494e-38
FLT_MAX = 3.402823e+38
DBL_MIN = 2.225074e-308
DBL_MAX = 1.797693e+308
float sum = 16777216.000000
double sum = 134217728.000000
sumval_d/sumval_f = 8.000000
Whilst compiling with icc the sumval_f = 67108864.0 and hence the final ratio is instead 2.0*. Note that the float sum is incorrect, whilst the double sum is correct.
As far as I can tell the output of FLT_MAX suggests that the sum should fit into a float, and yet it seems to plateau out at either an eighth or a half of the full value.
Is there a compiler specific override to the values found using float.h?
Why is a double required to correctly find the sum of this array?
*Interestingly the inclusion of an if statement inside the for loop that prints values of the array causes the value to match the gcc output, i.e. an eighth of the correct sum, rather than a half.
The problem here isn't the range of values but the precision.
Assuming a 32-bit IEEE754 float, this datatype has a maximum of 24 bits of precision. This means that not all integers larger than 16777216 can be represented exactly.
So when your sum reaches 16777216, adding 1 to it is outside the precision of what the datatype can store, so the number doesn't get any bigger.
A (presumably) 64-bit double has 53 bits of precision. This is enough bits to hold all integer values up to your sum of 134217728, so it gives you an accurate result.
A float can precisely represent any integer between -16777215 and +16777215, inclusive. It can also represent all even integers between -2*16777215 and +2*16777215 (including +/- 2*8388608, i.e. 16777216), all multiples of 4 between -4*16777215 and +4*16777215, and likewise for all power-of-two scaling factors up to 2^104 (roughly 2.028E+31). Additionally, it can represent multiples of 1/2 from -16777215/2 to +16777215/2, multiples of 1/4 from -16777215/4 to +16777215/4, etc. down to multiples of 1/2^149 from -167777215/(2^149) to +16777215/(2^149).
Floating point numbers represent all of the infinite possible values between any two numbers; but, computers cannot hold an infinite number of values. So a compromise is made. The floating point numbers hold an approximation of the value.
This means that if you pick a value that is "more" than the stored floating point number, but not enough to arrive at the "next" storable approximation, then storing that logically bigger number won't actually change the floating point value.
The "error" in a floating point approximation is variable. For small numbers, the error is more precise; for bigger numbers, the error proportionally the same, but a bigger actual value.
I don't understand why doesn't the roundf() function from math.h round the donation variable, whilst it rounds livestockPM without a problem. I need to use the rounded values for other calculations, but I'm using printf to check if the values are correct, and it simply returns wrong values (doesn't round variable donation). Also, the variable final only returns values as if rounded to .00, doesn't matter what variables farmer1,2,3 hold.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(){
int farmer1 = 9940;
int farmer2 = 4241;
int farmer3 = 7779;
float livestockPM = (float)farmer1 / (float)farmer2;
printf("livestock: %f\n",livestockPM);
livestockPM = roundf(livestockPM * 100) / 100;
printf("livestock rounded: %f\n",livestockPM);
float donation = (float)livestockPM * (float)farmer3;
printf("donation: %f\n", donation);
donation = roundf(donation * 100.00) / 100.00;
printf("donation rounded: %f\n", donation);
float final = donation * (float)farmer2;
printf("final: %f\n", final);
return 0;
}
Output:
livestock: 2.343787
livestock rounded: 2.340000
donation: 18202.859375
donation rounded: 18202.859375
final: 77198328.000000
Anyone got any idea why? I was thinking because of multiplying float with int, but I can't seem to get it work like this. I've tried removing the (float) from integer variables, but the results were undesirable as well. Thanks.
OP's float is encoded using binary floating point and 18202.859375 lacks precision to take on a value that "%f" prints as 18202.860000.
A float cannot represent every possible number. As a binary floating point number it can represent numbers like below. See IEEE 754 Converter, but not in between.
18202.859375
18202.86138125
When the following executes, the best possible result is again 18202.859375.
float donation_rounded = roundf(18202.859375 * 100.00) / 100.00;
Recall that printf("%f\n", x) prints a number rounded textually to the closest 0.000001 value.
Code could use double, but the same problem will occur with very large numbers, but may meet OP''s immediate need. #user3386109
As OP appears to be trying to cope with money, there is no great solution in standard C. best money/currency representation goes into some of the issues.
I'm new to C and when I run the code below, the value that is put out is 12098 instead of 12099.
I'm aware that working with decimals always involves a degree of inaccuracy, but is there a way to accurately move the decimal point to the right two places every time?
#include <stdio.h>
int main(void)
{
int i;
float f = 120.99;
i = f * 100;
printf("%d", i);
}
Use the round function
float f = 120.99;
int i = round( f * 100.0 );
Be aware however, that a float typically only has 6 or 7 digits of precision, so there's a maximum value where this will work. The smallest float value that won't convert properly is the number 131072.01. If you multiply by 100 and round, the result will be 13107202.
You can extend the range of your numbers by using double values, but even a double has limited range. (A double has 16 or 17 digits of precision.) For example, the following code will print 10000000000000098
double d = 100000000000000.99;
uint64_t j = round( d * 100.0 );
printf( "%llu\n", j );
That's just an example, finding the smallest number is that exceeds the precision of a double is left as an exercise for the reader.
Use fixed-point arithmetic on integers:
#include <stdio.h>
#define abs(x) ((x)<0 ? -(x) : (x))
int main(void)
{
int d = 12099;
int i = d * 100;
printf("%d.%02d\n", d/100, abs(d)%100);
printf("%d.%02d\n", i/100, abs(i)%100);
}
Your problem is that float are represented internaly using IEEE-754. That is in base 2 and not in base 10. 0.25 will have an exact representation, but 0.1 has not, nor has 120.99.
What really happens is that due to floating point inacuracy, the ieee-754 float closest to the decimal value 120.99 multiplied by 100 is slightly below 12099, so it is truncated to 12098. You compiler should have warned you that you had a truncation from float to in (mine did).
The only foolproof way to get what you expect is to add 0.5 to the float before the truncation to int :
i = (f * 100) + 0.5
But beware floating point are inherently inaccurate when processing decimal values.
Edit :
Of course for negative numbers, it should be i = (f * 100) - 0.5 ...
If you'd like to continue operating on the number as a floating point number, then the answer is more or less no. There's various things you can do for small numbers, but as your numbers get larger, you'll have issues.
If you'd like to only print the number, then my recommendation would be to convert the number to a string, and then move the decimal point there. This can be slightly complicated depending on how you represent the number in the string (exponential and what not).
If you'd like this to work and you don't mind not using floating point, then I'd recommend researching any number of fixed decimal libraries.
You can use
float f = 120.99f
or
double f = 120.99
by default c store floating-point values as double so if you store them in float variable implicit casting is happened and it is bad ...
i think this works.