# C programmers - float accuracy

**URL:** <https://boards.straightdope.com/t/c-programmers-float-accuracy/356393>\
**Category:** Factual Questions\
**Created:** [May 11, 2006, 5:27pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393 "2006-05-11T17:27:36Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![cmkeller](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/cmkeller/32/118_2.png) [@cmkeller](https://boards.straightdope.com/u/cmkeller)\
**Post date:** [May 11, 2006, 5:27pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/1 "2006-05-11T17:27:36Z")

</div>

I’m having some serious trouble in a C++ program I’m writing. I’m sure that this is a known issue in C/C++, but my question is, is there a known solution to it?

My problem is that on very, very big numbers, the numbers aren’t accurate. When I take the number 9999999999999.999, and make it a double float, it comes up as 9999999999999.998046875 When I take the number 9999999999999.99, and make it a double float, it comes up as 9999999999999.9902340275. I understand that the computer stores floats as base + exponent, and so there’s some inaccuracy when it expands that into a number we can see. What I want to know is, is there any known workaround for this problem?

If it matters, I’m programming in a Windows environment.

---

<div class="post-metadata">

**Author:** ![griffin1977](https://avatars.discourse-cdn.com/v4/letter/g/977dab/32.png) [@griffin1977](https://boards.straightdope.com/u/griffin1977)\
**Post date:** [May 11, 2006, 6:01pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/2 "2006-05-11T18:01:54Z")

</div>

Try this library for quad precision FP operations:

[http://crd.lbl.gov/~dhbailey/mpdist/index.html](http://crd.lbl.gov/~dhbailey/mpdist/index.html)

---

<div class="post-metadata">

**Author:** ![Voyager](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/voyager/32/133_2.png) [@Voyager](https://boards.straightdope.com/u/Voyager)\
**Post date:** [May 11, 2006, 6:05pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/3 "2006-05-11T18:05:48Z")

</div>

The issue is not with C++ or Windows, but with the limited precision you get from representing decimal numbers and fractions in binary. To fix this you need a software package that handles arbitrary precision. A quiclk google revealed one from Gnu called [MPBignum](http://www.swox.com/gmp/).  
I haven’t used this, but I have taken Numerical Analysis, and when I was in grad school we had a group working on interval arithmetic. There appear to be packages that cost money also, but I’m betting MPBignum will do what you need.

---

<div class="post-metadata">

**Author:** ![Punoqllads](https://avatars.discourse-cdn.com/v4/letter/p/d2c977/32.png) [@Punoqllads](https://boards.straightdope.com/u/Punoqllads)\
**Post date:** [May 11, 2006, 8:26pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/4 "2006-05-11T20:26:11Z")

</div>

The workaround depends upon what sort of functionality is lacking. For instance, if the issue is that your program needs to decide whether two floating-point numbers are the same, the workaround is to instead check if the difference between two numbers is within some delta. If the issue is that the numbers look ugly when you print them out, the workaround is to ensure that the print function prints no more than a certain number of digits (6 for floats, 16 for doubles). If the issue is that you require exact values for rational numbers (such as money), then a workaround is separating a given value into a numerator and a denominator.

---

<div class="post-metadata">

**Author:** ![iamthewalrus\_3](https://avatars.discourse-cdn.com/v4/letter/i/258eb7/32.png) [@iamthewalrus\_3](https://boards.straightdope.com/u/iamthewalrus_3)\
**Post date:** [May 11, 2006, 8:32pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/5 "2006-05-11T20:32:17Z")

</div>

It might help to know what it is you’re trying to do.

For most purposes, that’s plenty of accuracy. +/- 0.002 on a number in the trillions is really incredibly accurate. Do you actually _need_ more accuracy than that, or are you just put off by the fact that the numbers don’t act like you expect them to?

If it’s the second case, there are probably known workarounds to whatever you’re trying to do. For example, it’s problematic to compare two floats directly. (float1 == float2) is rarely going to return true if you arrived at the numbers through different code paths. Instead, what you do is include a fudge factor, and see if the difference between the two values is large enough to be considered significant.

Obviously, if you’re working with, say, money, you’d want arbitrary precision. But bear in mind that such precision comes with a cost. If you’re doing lots of calculations, that precision is going to slow you down considerably. For most real-world problems you’ll be solving, float or double accuracy is more than enough.

---

<div class="post-metadata">

**Author:** ![cmkeller](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/cmkeller/32/118_2.png) [@cmkeller](https://boards.straightdope.com/u/cmkeller)\
**Post date:** [May 11, 2006, 8:42pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/6 "2006-05-11T20:42:46Z")

</div>

The issue is that I need to ensure that the number the user enters does not contain more decimal places than the maximum allowed for that data category (which is configurable).

So if when the user enters 9999999999999.99 (for a category in which two decimal places are allowed), and the computer sees it as 9999999999999.990234, that’s a problem.

---

<div class="post-metadata">

**Author:** ![ultrafilter](https://avatars.discourse-cdn.com/v4/letter/u/3d9bf3/32.png) [@ultrafilter](https://boards.straightdope.com/u/ultrafilter)\
**Post date:** [May 11, 2006, 8:45pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/7 "2006-05-11T20:45:52Z")

</div>

Better to process it as a string. If you have a perl-like regular expression parser, match it against “(.)+.[0-9][0-9]”.

---

<div class="post-metadata">

**Author:** ![griffin1977](https://avatars.discourse-cdn.com/v4/letter/g/977dab/32.png) [@griffin1977](https://boards.straightdope.com/u/griffin1977)\
**Post date:** [May 11, 2006, 8:48pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/8 "2006-05-11T20:48:13Z")

</div>

Yes definitely, if you don’t need to do any arithmetic operations on it, and your only interested in the number of decimal places, just use strings…

---

<div class="post-metadata">

**Author:** ![ultrafilter](https://avatars.discourse-cdn.com/v4/letter/u/3d9bf3/32.png) [@ultrafilter](https://boards.straightdope.com/u/ultrafilter)\
**Post date:** [May 11, 2006, 8:51pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/9 "2006-05-11T20:51:16Z")

</div>

> [@ultrafilter](#):
>
> Better to process it as a string. If you have a perl-like regular expression parser, match it against “(.)+.[0-9][0-9]”.

Actually, that should be “[0-9]+.[0-9][0-9]”. You don’t want abc.99 to match, right?

---

<div class="post-metadata">

**Author:** ![mks57](https://avatars.discourse-cdn.com/v4/letter/m/b9bd4f/32.png) [@mks57](https://boards.straightdope.com/u/mks57)\
**Post date:** [May 11, 2006, 8:58pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/10 "2006-05-11T20:58:30Z")

</div>

See [http://www2.hursley.ibm.com/decimal/](http://www2.hursley.ibm.com/decimal/) for a great resource on decimal arithmetic.

If your numbers can be represented as large integers, you can use IEEE double precision floating point to do exact arithmetic on integers up to the size of the mantissa, about 53 bits. I’ve used this for things like representing time as the number of microseconds that have elapsed since an epoch. For financial calculations, some programmers use large integers to represent cents or fractions of cents. For example, $1,234,567.89 is stored as 123456789.

---

<div class="post-metadata">

**Author:** ![griffin1977](https://avatars.discourse-cdn.com/v4/letter/g/977dab/32.png) [@griffin1977](https://boards.straightdope.com/u/griffin1977)\
**Post date:** [May 11, 2006, 8:58pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/11 "2006-05-11T20:58:53Z")

</div>

assuming you know it is a valid number prob easier just to use C. Something like this:

pCh=pEndOfString;  
int n;  
while(pCh\>=pStartOfString && \*pCh!=’.’)  
pCh–;

int numDP=0;  
if(pCh\>=pStartOfString)  
numDP=(int)pEndOfString-(int)pCh;

---

<div class="post-metadata">

**Author:** ![cmkeller](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/cmkeller/32/118_2.png) [@cmkeller](https://boards.straightdope.com/u/cmkeller)\
**Post date:** [May 11, 2006, 9:07pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/12 "2006-05-11T21:07:19Z")

</div>

That was the way I was going to do this in the first place. The problem is that when I format it as a string ("%lf") it comes out the bad way, with .99 being formatted as .990234 .

---

<div class="post-metadata">

**Author:** ![Punoqllads](https://avatars.discourse-cdn.com/v4/letter/p/d2c977/32.png) [@Punoqllads](https://boards.straightdope.com/u/Punoqllads)\
**Post date:** [May 11, 2006, 9:13pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/13 "2006-05-11T21:13:27Z")

</div>

> [@cmkeller](#):
>
> That was the way I was going to do this in the first place. The problem is that when I format it as a string ("%lf") it comes out the bad way, with .99 being formatted as .990234 .

This implies that the number is being read in as a double, and that you’re converting it into a string. What people are saying to do is to read in the input as a string, verify that that follows the form you would like, and then convert that string into a double.

Perhaps you could give us a code snippet?

---

<div class="post-metadata">

**Author:** ![bup](https://avatars.discourse-cdn.com/v4/letter/b/6bbea6/32.png) [@bup](https://boards.straightdope.com/u/bup)\
**Post date:** [May 11, 2006, 9:18pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/14 "2006-05-11T21:18:11Z")

</div>

> [@cmkeller](#):
>
> That was the way I was going to do this in the first place. The problem is that when I format it as a string ("%lf") it comes out the bad way, with .99 being formatted as .990234 .

Or, put it in a string, and truncate it two places after the decimal.

---

<div class="post-metadata">

**Author:** ![cmkeller](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/cmkeller/32/118_2.png) [@cmkeller](https://boards.straightdope.com/u/cmkeller)\
**Post date:** [May 11, 2006, 9:35pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/15 "2006-05-11T21:35:58Z")

</div>

Punoqllads:

> [@](#):
>
> This implies that the number is being read in as a double, and that you’re converting it into a string. What people are saying to do is to read in the input as a string, verify that that follows the form you would like, and then convert that string into a double.

The number is actually being read in as a COM Variant, with the type being VT\_DECIMAL. And when I debug and see that value, I see the exact thing the user put in. However, in order to format that into a string, I need to cast it to a double.

The option to read it as a string in the first place is not available to me. I need to check the decimal value against the configured maximum number of decimal places.

bup:

> [@](#):
>
> Or, put it in a string, and truncate it two places after the decimal.

If I truncate it, I’m forcing the value to be a valid value, not checking that the value the user put in is valid.

---

<div class="post-metadata">

**Author:** ![ultrafilter](https://avatars.discourse-cdn.com/v4/letter/u/3d9bf3/32.png) [@ultrafilter](https://boards.straightdope.com/u/ultrafilter)\
**Post date:** [May 11, 2006, 9:38pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/16 "2006-05-11T21:38:07Z")

</div>

If it’s being read in as a double, you’re pretty much screwed.

---

<div class="post-metadata">

**Author:** ![Punoqllads](https://avatars.discourse-cdn.com/v4/letter/p/d2c977/32.png) [@Punoqllads](https://boards.straightdope.com/u/Punoqllads)\
**Post date:** [May 11, 2006, 9:48pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/17 "2006-05-11T21:48:20Z")

</div>

> [@cmkeller](#):
>
> The number is actually being read in as a COM Variant, with the type being VT\_DECIMAL. And when I debug and see that value, I see the exact thing the user put in. However, in order to format that into a string, I need to cast it to a double.

What’s wrong with using VariantToString?  
[http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/en-us/ShellCC/platform/shell/reference/functions/propvarconversionfunctions/varianttostring.asp](http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/en-us/ShellCC/platform/shell/reference/functions/propvarconversionfunctions/varianttostring.asp)

---

<div class="post-metadata">

**Author:** ![griffin1977](https://avatars.discourse-cdn.com/v4/letter/g/977dab/32.png) [@griffin1977](https://boards.straightdope.com/u/griffin1977)\
**Post date:** [May 11, 2006, 9:52pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/18 "2006-05-11T21:52:22Z")

</div>

My COM knowledge is pretty much non-existent but I beleive VT\_DECIMAL is DECIMAL type. This is a 16-byte fixed point format. From the docs on PROPVARIANT:

> [@](#):
>
> The PROPVARIANT structure can also hold a value of VT\_DECIMAL:  
> DECIMAL decVal; //VT\_DECIMAL
> 
> However, the value of the DECIMAL structure requires special handling. The DECIMAL structure is the same size as an entire PROPVARIANT structure and does not fit into the union that holds all other types of values. Instead, the value of the DECIMAL structure occupies the entire PROPVARIANT structure, including the reserved fields and the vt member. However, the first member of the DECIMAL structure is not used and is equal in size to the vt member of the PROPVARIANT structure. Therefore, the PROPVARIANT structure declaration in the propidl.h header file of Microsoft® Win32® defines the decVal member in such a way that it corresponds to the beginning of the PROPVARIANT structure. Therefore, to put the value of the DECIMAL structure into a PROPVARIANT structure, the value must be loaded into the decVal member and the vt member is set to VT\_DECIMAL, just as for any other value.
> 
> PROPVARIANT is the fundamental data type by which property values are read and written through the IPropertyStorage interface.
> 
> The data type PROPVARIANT is related to the data type VARIANT, defined as part of Automation in OLE2. Several definitions are reused from Automation, as follows:
> 
> typedef struct tagDEC {  
> USHORT wReserved;  
> BYTE scale;  
> BYTE sign;  
> ULONG Hi32;  
> ULONGLONG Lo64;  
> } DECIMAL;

---

<div class="post-metadata">

**Author:** ![cmkeller](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/cmkeller/32/118_2.png) [@cmkeller](https://boards.straightdope.com/u/cmkeller)\
**Post date:** [May 11, 2006, 10:00pm UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/19 "2006-05-11T22:00:29Z")

</div>

> [@](#):
>
> What’s wrong with using VariantToString?

Good, that’s the sort of thing I’d been looking for…I’ll see if it does the trick for me.

---

<div class="post-metadata">

**Author:** ![cmkeller](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/cmkeller/32/118_2.png) [@cmkeller](https://boards.straightdope.com/u/cmkeller)\
**Post date:** [May 12, 2006, 7:23am UTC](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393/20 "2006-05-12T07:23:12Z")

</div>

No dice. Function looks nice on paper, but until Windows Vista comes out, on paper is where it stays.

[Next page](https://boards.straightdope.com/t/c-programmers-float-accuracy/356393.md?page=2)
