Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving decimal place to right in c

Tags:

c

double

decimal

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);
}
like image 799
Robert Avatar asked Feb 04 '15 17:02

Robert


People also ask

How do you move decimal places to the right?

If you multiply a decimal by 10, the decimal point will move one place to the right. If you divide a decimal by 10, the decimal point will move one place to the left.

How do you move the decimal point left or right?

If there IS a decimal point, move it to the right the same number of places that there are 0s. When dividing by 10, 100, 1000 and so on, move the decimal point to the left as many places as there are 0s. So when dividing by 10, move the decimal point one place, by 100 two places, by 1000 three places and so on.

What is 2f in C?

2f" tells the printf method to print a floating point value (the double, x, in this case) with 2 decimal places.


4 Answers

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.

like image 94
user3386109 Avatar answered Oct 17 '22 14:10

user3386109


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);
}
like image 45
zwol Avatar answered Oct 17 '22 13:10

zwol


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 ...

like image 2
Serge Ballesta Avatar answered Oct 17 '22 15:10

Serge Ballesta


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.

like image 1
Bill Lynch Avatar answered Oct 17 '22 13:10

Bill Lynch