CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com

Thread: floating point number formatting question

1. Senior Member
Join Date
Feb 2009
Location
Portland, OR
Posts
1,488

floating point number formatting question

Hi everyone:

Say, if I want to format a floating point number pretty much like it's done in mathematics (see example below). I do not need precision of more than two decimal numbers. Is there a printf formatting specifier that can do this?

Examples:

1.0000 becomes "1"
1.30 becomes "1.3"
1.32 becomes "1.32"
1.38 becomes "1.38"
1.322 becomes "1.32"
1.325 becomes "1.33"

2. Elite Member Power Poster
Join Date
May 2005
Posts
4,954

Re: floating point number formatting question

One way:

Code:
```float Num=1.333f;
char Buf[128]={0};
sprintf(Buf,"%.2f",Num);
// Buf = "1.33"```
Cheers

3. Elite Member Power Poster
Join Date
Aug 2000
Location
New York, NY, USA
Posts
5,656

Re: floating point number formatting question

Originally Posted by golanshahar
One way:

Code:
```float Num=1.333f;
char Buf[128]={0};
sprintf(Buf,"%.2f",Num);
// Buf = "1.33"```
Cheers
I think this will fail test cases 1, 2 and 6.

4. Re: floating point number formatting question

"&#37;.3g" can print all those values that you wanted. However, the precision here indicates the number of digits to be printed, before and after the decimal point. So if you're numbers have 2 digits before the decimal point, you must use "%.4g". So this can only work if you always have the same number of digits, and I guess that's not the case.

5. Senior Member
Join Date
Feb 2009
Location
Portland, OR
Posts
1,488

Re: floating point number formatting question

Thank you, guys.

No, neither "%.2f" nor "%.4g" will solve it. The first option simply uses 2 decimal numbers and the 'g' option can switch to the exponential output that I do not need in my case.

So, having done some research I see that there's no easy way to do what I need. So now the question is, what is the easiest way to do this with a custom function?

Something like this?
Code:
```void print_custom_float(double fValue)
{
if((int)fValue == fValue)
{
_tprintf(_T("%d"), (int)fValue);
}
else if((int)(fValue * 10) == fValue * 10)
{
_tprintf(_T("%.1f"), fValue);
}
else
{
_tprintf(_T("%.2f"), fValue);
}
}```

6. Re: floating point number formatting question

if((int)fValue == fValue)
You never should compare floats like this. Actually it should be delta comparison:
Code:
`if(abs(fValue - (int)fValue) < 0.000001)`

7. Re: floating point number formatting question

Originally Posted by Igor Vartanov
You never should compare floats like this. Actually it should be delta comparison:
Code:
`if(abs(fValue - (int)fValue) < 0.000001)`
Only to get the correct result in this case the epsilon should be 0.005. That way 1.001 will be printed as 1, instead of 1.00.

8. Senior Member
Join Date
Feb 2009
Location
Portland, OR
Posts
1,488

Re: floating point number formatting question

Yes, good point, both of you. I posted it too quick w/o giving it a second thought. It should probably be re-written to something like this:
Code:
```#include <Math.h>
void print_custom_float(double fValue)
{
if(fabs(fValue - (__int64)fValue) < 0.001)    //For 2 decimal numbers
{
_tprintf(_T("&#37;I64d"), (__int64)fValue);
}
else
{
int nValueMult100 = (int)(fabs(fValue - (__int64)fValue) * 100.0 + 0.5);
if(nValueMult100 % 10)
{
_tprintf(_T("%.2f"), fValue);
}
else
{
_tprintf(_T("%.1f"), fValue);
}
}
}```
Unless someone can come up with a faster (less straightforward) solution?
Last edited by ahmd; May 23rd, 2011 at 12:42 PM.

9. Elite Member Power Poster
Join Date
Oct 2007
Location
Seattle, WA
Posts
10,895

Re: floating point number formatting question

Originally Posted by ahmd
So, having done some research I see that there's no easy way to do what I need.
You could format the output to always have exactly 2 decimal places, even if they are 0, easily enough. This is done with std::fixed for ostreams and, I think, %f for printf().

Then, once you've created this output string, you can simply drop trailing characters which are '0' (and '.' if you reach it, but stop there). Then write the modified string to the screen.

10. Senior Member
Join Date
Feb 2009
Location
Portland, OR
Posts
1,488

Re: floating point number formatting question

Originally Posted by Lindley
You could format the output to always have exactly 2 decimal places, even if they are 0, easily enough. This is done with std::fixed for ostreams and, I think, %f for printf().

Then, once you've created this output string, you can simply drop trailing characters which are '0' (and '.' if you reach it, but stop there). Then write the modified string to the screen.
Thanks for your insight but I'd rather not deal with string representation of numbers. There are many reasons for that and mainly localization -- you don't know how a certain number may be converted to a string for a certain user locale.

11. Elite Member Power Poster
Join Date
Aug 2000
Location
New York, NY, USA
Posts
5,656

Re: floating point number formatting question

Originally Posted by ahmd
Thanks for your insight but I'd rather not deal with string representation of numbers. There are many reasons for that and mainly localization -- you don't know how a certain number may be converted to a string for a certain user locale.
I agree with Lindley. Also, I am not aware of any locale in which the following won't work (this, of course, is not a guarantee):
Code:
```void MyPrint(float Num)
{
char Buf[128]={0};
int length = sprintf(Buf, "%.2f", Num);
while(Buf[length-1] == '0')
Buf[--length] = 0;
if(!isdigit(Buf[length-1]))
Buf[--length] = 0;

printf("%s\n", Buf);
}

int _tmain(int argc, _TCHAR* argv[])
{
MyPrint(1.0000);
MyPrint(1.30);
MyPrint(1.32);
MyPrint(1.38);
MyPrint(1.322);
MyPrint(1.325);
return 0;
}```

12. Senior Member
Join Date
Feb 2009
Location
Portland, OR
Posts
1,488

Re: floating point number formatting question

Well, that might be an alternate solution. Thanks.

I agree with Lindley. Also, I am not aware of any locale in which the following won't work (this, of course, is not a guarantee)
Well, that's something that would alarm me -- not knowing if it'd work everywhere -- and that is why I prefer dealing with numbers rather than strings (if I have a choice, of course).

13. Elite Member Power Poster
Join Date
Aug 2000
Location
New York, NY, USA
Posts
5,656

Re: floating point number formatting question

Originally Posted by ahmd
Well, that's something that would alarm me -- not knowing if it'd work everywhere -- and that is why I prefer dealing with numbers rather than strings (if I have a choice, of course).
Well, your code fails with 1.998 (prints 2.0).

14. Senior Member
Join Date
Feb 2009
Location
Portland, OR
Posts
1,488

Re: floating point number formatting question

Well, your code fails with 1.998 (prints 2.0).
Thanks for pointing it out. This made me find a simpler solution. Check this out:
Code:
```#include <Math.h>
void print_custom_float(double fValue)
{
int nValueMult100 = (int)(fabs(fValue - (__int64)fValue) * 100.0 + 0.5);
if(nValueMult100 % 10)
{
_tprintf(_T("%.2f"), fValue);
}
else if(nValueMult100 % 100)
{
_tprintf(_T("%.1f"), fValue);
}
else
{
_tprintf(_T("%.0f"), fValue);
}
}```

15. Elite Member Power Poster
Join Date
Aug 2000
Location
New York, NY, USA
Posts
5,656

Re: floating point number formatting question

Originally Posted by ahmd
This made me find a simpler solution. Check this out...
Or like that:
Code:
```void print_custom_float(double fValue)
{
int nValueMult100 = (int)(fabs(fValue - (__int64)fValue) * 100.0 + 0.5);
int n = (nValueMult100 % 10) ? 2 : (nValueMult100 % 100) ? 1 : 0;
_tprintf(_T("%.*f\n"), n, fValue);
}```

Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•