Formatting a double number without rounding off

Jan 15, 2010 at 6:10am
Hi,
I wanted to know is there any way to represent the double number without rounding it off.

Well i have a double number let's say 0.123456789123456789123456789(27 digits after decimal) on windows platform.

And i am converting this number to a string and i dont want any rounding off so i am using
sprintf(buffer,".27f",Number), but windows can support till 18 digits, so the buffer will contain the number till 18 digits only and rest will be zero, the buffer will contain
0.123456789123456780000000000

Okay i have another option to use sprintf(buffer,".27g",Number), but by this operation the buffer will contain 0.12345678912345678.

I know that hardware architecture plays an important role for representing the double number, but double number takes 64 bits out oh which 1 bit is for sign , 11 bits are exponential and rest for mantissa part, so while representing the number as in the above example using %.27g ,i guess its not making use of the exponential digits.

So is there any way that i can represent any double number without rounding it off, because these standard methods of using sprintf are not working.
Jan 15, 2010 at 6:21am
Well to the above i have did some research on the type of formatting, i guess that can be useful.

Even though we can use any formatting for double values but depending on the OS it will format with in its limit,

that means to say if i have some value as 0.11212234545465657676878787879(29 digits after decimal) on windows platform

now if i want to display the full number without loosing any digit, so one might use " sprintf(buffer,"%.29f",theValue) " but we get only 18 digits and rest being truncated, since windows supports till 18 digits.

Moreover if we are taking the double values from the DB and trying to print it again depends on the OS on
which we are working.

for example, if the DB precision has 15 and windows supports till 18 digits, then the value which we are printing will be wrong since last three digits is junk.

Usage of "f"(%f, %.14f) and g (%g,%.14g)

"f" has the advantage of maintaining the precision after the decimal ,reason being "f" formatting
is applied only on the decimal digits but "g" formatting takes the siginificant digits as well for formatting.

Forexample:

double dValue = 32.123456788901245

For the above value sprintf(buf,"%.14f", dValue) yields 32.12345678890125 (total digits 16)

and for the same value sprintf(buf,".14g",dValue) yields 32.123456788901 (total digits=14)


But if the number is very small then using f formatting we will loose the digits, but "g" will convert into exponential formatting and will retain the digits.

If we use %.14g and the number is smaller than 0.0001 the it will convert into exponential format, and if it is some what greater than this number then while doing formatting it ignores the number of zeros after decimal.

Example::

(1) double dValue = 0.00000123456789456;

sprintf(buf, "%.14f", dValue) yields 0.00000123456789

sprintf(buf, "%.14g", dValue) yields 1.23456789456e-006

(2) double dValue = 0.00123456789122345

sprintf(buf,"%.14f",dValue) yields 0.00123456789122

sprintf(buf,"%.14g",dValue) yields 0.0012345678912235(It has ignored zeros after the decimal and hence total 17 digits)

(3) double dValue = -47321.632599999999145

sprintf(buf,"%.14f",dValue) yields -47321.63259999999915

sprintf(buf,%.14g",dValue) yields -47321.6326

(4) double dValue = -47321.00000000000012

sprintf(buf,"%.14f",dValue) yields -47321.00000000000012


So my question is there any way i can print the exact value of the decimal, and ya i m not bother about the recurring decimal.

Jan 15, 2010 at 6:25am
Hmmm... I have an idea but I don't know if it is possible.

Separate the number into two parts by using addition.

For example:

0.123456789123456789123456789

to
0.12345678912345678 + 0.000000000000000009123456789

convert 0.000000000000000009123456789 to its exponential form

9.123456789 x 10 ^ (-18)

then add the two

0.12345678912345678 + 9.123456789 x 10 ^(-18)

I don't know it this will work but if you have time give it a try.

Hope this helps. It's just an idea of mine.
Last edited on Jan 15, 2010 at 6:26am
Jan 15, 2010 at 6:47am
I don't know where you're getting this "windows supports 18 digits" nonsense from. This has nothing to do with Windows and everything to do with the FPU.

64 bits out oh which 1 bit is for sign , 11 bits are exponential and rest for mantissa part". So you're left with 52 mantissa bits.


You're right about this. By my calculations... this gives you:

2^52 = 4503599627370496 = only 16 digits (but really can only fully represent 15 digit numbers)

Of course on the FPU, the registers may be wider than 64 bits, so you may end up with some additional digits. For more you can read this:

http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.18

So is there any way that i can represent any double number without rounding it off, because these standard methods of using sprintf are not working.


The variable simply isn't wide enough to hold this large of a number. 27 digits is massive. Far too massive to hold in a double. I figure you'd need at least 90 or 91 bits of mantissa to hold 27 digits without losing any.


EDIT:

So the answer to your question is: No.

If you want a 27 digit number, you'll need to use a [much] larger data type, and such a data type would not work with standard I/O routines like sprintf.

Try looking into bignum libs. I forget the name of them, but they allow you to have extremely wide variables. They might also have string formatting capbilities as well. I wish I could recommend one but I never have use of this kind of thing so I've never looked.
Last edited on Jan 15, 2010 at 6:52am
Jan 15, 2010 at 7:10am
Hi Disch,

Thanks for replying.

Well i know that the precision comes from mantissa part and is calculated as log10(2^52) which is nearly equal to 16 digits, but lets say i will take the 11 digits of the exponent also then we can have the precision of nearly log10(2^62) which is nearly equal to 18, so i guess because of this i am getting this non sense form. I don't know i am just making a guess.

if u try formatting the number using sprintf(buffer,".14f",Number) then u might see 18 digits.

Anyways i have found that multi precision is possible irrespective of the hardware architecture, but i don't know about the internals, so can you please help me out.
The link for the same is

http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic
Jan 15, 2010 at 7:19am
You can't use the exponent bits for the mantissa because they're used for the exponent. If you don't need an exponent, you're better off with an integral (read: not floating point) type. long long will get you 64-bits on most compilers... but that's still a far cry away from the 92 you're demanding.

As for arbitrary precision aritmetic, that's exactly what bignum libs do. Look them up.

Here's one I found by googling:

http://gmplib.org/
Jan 15, 2010 at 8:16am
I see. Thanks Disch.

Well how about converting the input to array first?
char number[29]; //??
then make a for loop?
1
2
3
4
5
6
7
8
for(i = 0; i<29; i++){
            if(i == 1)
                 number[i] = "."
            number[i] = //(get the position of the number)
}

//then convert the array into string.
string mystr = number; //something like this. 


Hmmm.... number to array then array to string...
Well, I think this algorithm is not efficient at all.

Goodluck!
Topic archived. No new replies allowed.