tags:

views:

329

answers:

8

Lets consider we have a double R = 99.999999; (which may be obtained by a result of some other computation),now the desired output is 99.99

I tried using printf("%.2lf",R); but it's rounding off the value.How to get the desired output ? (preferably using printf)

A: 

Can you multiply by 100 and then truncate to an integer? Then you could format the result like one would with dollars and cents. Simply dividing by 100 might land you back at square one due to floating-point representation issues.

Kristo
Not really. Standard double floating point representations are accurate to 15 digits. So unless the OP is dealing with numbers in the ten billions of dollars range he should be fine. In any case, multiplication runs into the same floating-point representation issues.
Billy ONeal
+2  A: 

sprintf it into a buffer, and then put the NUL char two bytes past the '.'

Then printf your final string using the intermediate one.

quixoto
A: 

What about using double trunc(double) from GLibC?

Romain
Because not everybody is using GLibC.
Billy ONeal
@Billy The question doesn't say "I don't want to use GLibC", so answer is valid, right ? :)
Romain
Yes, it's valid. That's why I didn't downvote. That doesn't necessarily make it good. :)
Billy ONeal
@Billy: I never attempted to argue it was a *good* solution ;)
Romain
+10  A: 
#include <math.h>
...
    printf("%.2f", floor(100 * R) / 100);
Hans Passant
+1 but since the question is tagged C++ possibly also provide the C++ iostream way?
Mark B
Are there some odd cases where this gives the wrong answer? I'm not certain, but does there exist a floating point value f and an integer n such that f is less than the exact value of n/100, but the floating point result of f*100 is greater than or equal to n? Of course you can question whether it matters that f is truncated "incorrectly", since in "base 10 space" it represents a range which straddles a 0.01 marker.
Steve Jessop
Are negative numbers possible? With -99.999, multiply to -9999.9, floor is -10000, and the result is -100.
David Thornley
@Steve: yes, kind of: it does not work with 90071992547410.016 (which is printed as 90071992547410.02).
RaphaelSP
@David: I guess it should be `(R > 0 ? floor(100 * R) : ceil(100 * R)) / 100`
RaphaelSP
+4  A: 

All you have to do is subtract .005 from the number and magically printf will behave as you wish: always round down.

frankc
Unless the number is negative. Then it will blow up.
Billy ONeal
You beat me to the edit...it doesn't blow up. It just does the reverse. In this case, add .005.
frankc
Doesn't that seem a bit more complicated than nobugz' answer for no gain? Sure, you save a division and multiplication, but you trade it for a branch dependence (which is worse), and code that much less clearly expresses your intent.
Billy ONeal
So use `R + (R>0 ? -0.005 : 0.005)`, basically...
Romain
@BillyONeal: what makes you so sure that the performance difference between a division and a branch is (a) definitely one way or the other, (b) significant when immediately followed by a call to `printf`? I'd have thought it would at least depend on whether the platform has floating-point hardware or not: division is likely not going to be cheaper than a single branch if it's done in software.
Steve Jessop
@Steve Jessop: Perhaps that's platform dependent, but on the machines most of us are using, things are being done in hardware. But in any case, the intent is more important here. user275455's solution is non-obvious, nobugz' is obvious. That alone is compelling reason to use that method.
Billy ONeal
@Billy maybe, maybe not. I don't it's any less clear than any other solution. All of them are likely to include the comment /* force printf to truncate to two decimal places */ so it seems irrelevant. If your domain is definitely restricted to either positive or negative numbers, then I think the solution is clearly this best performing.
frankc
Not to mention, the multiplication solution is more likely to suffer from overflow.
frankc
@user275455: it won't overflow in any situation where it hasn't already lost precision long, long ago. It's meaningless to round a number to a multiple of .01 if it's within a factor of 100 of FLOAT_MAX.
Steve Jessop
A: 

Another solution, using casts:

...
printf("%.2lf", (double) ((int) (R * 100)) / 100);
Juliano
This isn't well-defined if R can be negative.
David Thornley
I've tested in Borland C++ Builder and it worked for both negative and positive values.
Juliano
A: 

Another way, truly sign agnostic: printf("%d.%d\n", (int) r ,abs((int)(r*100) % 100));

frankc
+2  A: 

If you have it, use fmod() to chop the tail of the double:

double rounded = R - fmod(R, 0.01);
// Now just print rounded with what you were using before

This has the advantage of working the same if R is positive or negative.

Donal Fellows