• 0

FLOAT and DOUBLE in Visual Studio is garbage?


Question

I am having some problems with visual studio 2005 professional,

I am declaring a simple double to 0.7 but in runtime it is 0.699999999999996 which is not CLOSE ENOUGH precision for my program...

I was wondering if this is a normal thing, or is it a bug in visual studio or is my hardware broken...?

check the image for a break/debug right after a few doubles have been allocated, you can see my code and you can see whats in mem..

the following info is to try and give a bigger picture of my system:

OS Name Microsoft? Windows Vista? Ultimate

Version 6.0.6000 Build 6000

System Manufacturer FUJITSU SIEMENS

System Model Amilo Mx43y Series

System Type X86-based PC

Processor Intel® Pentium® M processor 1.73GHz, 1733 Mhz, 1 Core(s), 1 Logical Processor(s)

BIOS Version/Date American Megatrends Inc. 1.10C, 05/10/2005

SMBIOS Version 2.3

Hardware Abstraction Layer Version = "6.0.6000.16386"

Total Physical Memory 2,046.81 MB

Microsoft Visual Studio 2005

Version 8.0.50727.867 (vsvista.050727-8600)

Microsoft .NET Framework

Version 2.0.50727

Installed Edition: Professional

Microsoft Visual C++ 2005 77626-009-0000007-41812

Microsoft Visual C++ 2005

Microsoft Visual Studio 2005 Professional Edition - ENU Service Pack 1 (KB926601)

Update for Microsoft Visual Studio 2005 Professional Edition - ENU (KB932232)

post-2527-1183128508_thumb.jpg

14 answers to this question

Recommended Posts

  • 0

Uh. I recommend reading up on the differences between basic data types....If you need absolutely perfect precision, you'll need some kind of BCD-type to store your numbers.

A double is a 64bit floating point number, which is only accurate to like 18ish (Maybe less?) decimal points. After that it does some rounding.

Also, you're programming in c++, Visual Studio is just an IDE, and kinda irrelevent to the question. (Just a tip)

Anyway.

Try using a long double.

Edited by MioTheGreat
  • 0
  noroom said:
That's what Double.Epsilon is for.

That's .NET.

Anyway, I take back what I said above, a long double and a double are the same thing w/ msvc++. They don't have extended precision doubles (Apparently, according to an MSDN blog, it might come in VC9).

You'll have to roll your own or find a sample online with a higher precision float, or a BCD (Which would be slower than the other option, but much more precise)

  • 0

in this case I just needed 0.7 as a nice number, when I saw that it wasnt what I specified I got worried that something might be broken somewhere, I remember reading about how NASA couldnt use the pentium cpu because it calculated numbers wrong... so I got a bit worried.. ;)

thanks for your replies, it really helped me to understand how things work. still I find it weird that I specify 0.7 but it doesnt store it like that...

I tried the same thing in C# and 0.7 is 0.7 in there...

  • 0

Yeah, this one is easy to understand. In fact, it happens very often and very easily if you aren't careful.

What's going on? Consider the value 0.5. That is easily representable in binary because binary uses powers of two. In the case of fractional parts, it works the same way as in decimal:

0.5 = 5 * 10^(-1) = 5 * 1/10 = 5/10 = 1/2

0.1b = 1 * 2^(-1) = 1 * 1/2 = 1/2

Obviously, for negative powers of 2, it is easy to store:

0.25 = 2 * 10^(-1) + 5 * 10^(-2) = 2/10 + 5/100 = 20/100 + 5/100 = 25/100 = 1/4

0.01b = 0 * 2^(-1) + 1 * 2^(-2) = 0 + 1 * 1/4 = 0 + 1/4 = 1/4

However, what about 1/5 (0.2)?

0.2 = 2 * 10^(-1) = 2 * 1/10 = 2/10 = 1/5

0.00110011...b = 1 * 2^(-3) + 1 * 2^(-4) + 1 * 2^(-7) + 1 * 2^(-8) + .... = 1/5

As you can see, unlike in decimal, 1/5 written in binary is a repeating value, just as 1/3 is in decimal.

You are also probably wondering how I got that value, right? The method that I've found easiest to understand is displayed here:

 x = 1 / 5
 y = "."

 x = x * 2 //multiply the value by the number base
 If x >= 1.0 Then // if x > 1 then
	 x = x - 1.0  // subtract 1 from x
	 y = y + "1" // and add a form of "carry" to a string containing the binary
 Else
	 y = y + "0"
 End If
 // repeat the multiplication process until x = 0
 // or until you find a recognizable repetition in y
 // or until the string exceeds the precision of the data type you are using

To illustrate, I'll use 1/5 as an example as if the above pseudocode actually ran and the comment about repeating the multiplication was implemented as some form of loop already:

1/5 * 2 = 2/5

2/5 >= 1 ?? No - ".0"

2/5 * 2 = 4/5

4/5 >= 1 ? No - ".00"

4/5 * 2 = 8/5

8/5 >= 1 ? Yes - ".001" // 8/5 - 1 = 3/5

3/5 * 2 = 6/5

6/5 >= 1 ? Yes - ".0011" // 6/5 - 1 = 1/5

We're back to 1/5, which is obviously where we started. Therefore, we can deduce that 1/5 repeats the 0011 combination.

Note that the above method actually works for any base:

// Hexadecimal

1/5 * 16 = 16/5

16/5 >= 1 ? Yes - ".3" // 16/5 - int(16/5) = 1/5

Since 1/5 ended up being 1/5 again, we have no need for testing again because we know that it will end up being the same thing. But why the .3 this time? Simply put, when you integer divide 16 by 5, you get 3. That value is the value that you need to use for the decimal. Also note the following way to check:

every group of 4 binary digits (bits) is equal to one hexadecimal digit (sometimes known as a hexit or hex bit). In other words, look at the following from the example:

.00110011

notice the 1s? Split them up!

. 0011 0011

Now convert them to hexadecimal:

. 3 3

The result for each group is 3, just like when the hexadecimal conversion was done.

This is probably confusing to you now. However, if you practice the conversion a couple of times, it is not that difficult.

Just remember that you check to see if the fraction is greater than or equal to 1 since the fraction should be less than 1 (if it is more than one, only part of the value is a fraction ;)). If it is greater than or equal to 1, you need to subtract the integer part of the value and you also need to add the integer part of the value to a string containing the values to give you your fraction in whatever base you want. Otherwise, you add a 0 to that string.

  • 0

Try this out:

http://www.alphaworks.ibm.com/tech/decnumb...usplus/download

Or, you can switch over to Managed C++ and use the System.Decimal class which is built in. (You might be using managed c++ for all I know, I can't tell based on what you've told us)

Edited by MioTheGreat
  • 0

You could also try using GMP (the GNU Multi-Precision library). There is a static build and a dynamic build for Visual C++ here as well as the source code to GMP and patches for the source code apparently -

http://cs.nyu.edu/exact/core/gmp/

Using System.Decimal would probably be the best solution since it should be a relatively similar syntax (rather than learning a whole new language by using a 3rd-party library).

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • A 10% IPC boost is underwhelming for what is supposed to be a major generational leap. Unless it's accompanied by higher clock speeds, or the IPC boost is greater than 10% in games, I'm not sure that it will be enough to compete with Zen 5 X3D, let alone Zen 6 X3D for gaming. Single-core performance is super important and cannot be compensated with more cores, whereas the reverse is true, you can compensate for fewer cores with better single-core performance.
    • Been happy with Windows 11 myself even since first release in 2021, sure it hasn't always been perfect, but nothing is per say.. Issues i did have was minor ones, which is normal with any OS really. I still use Windows 10 at times on my unsupported Gaming Laptop, and i find myself using the Windows 11 Desktop more. Eventually replacing Gaming Laptop with a Windows 11 Compatible one somehow, someway this year or possibly next year at the latest, but its gonna happen--(May save all my Bing reward points except the 1000 to have extended support for 10) then work on getting quality Replacement hard)
    • Geez, this is dumb. I use my laptop sometimes in the dark when doing astrophotography to control my astro-PC... this explains why I have to keep entering my PIN when logging back in. So stupid. I can't see the keyboard in the dark, and I can't have lights everywhere to light it up because everything is very light sensitive (including my eyes!).
    • Naturally. I don't care about brand loyalty at all as it's all about price/performance/reliability etc (even what RejZoR said below is a great point to). basically bang-for-the-buck. because at the end of the day... one wants the cheapest possible price to maintain a certain minimum level of performance (or thereabouts). because generally after a certain point with CPU and GPU's the price starts to sky rocket without that much difference in performance where it really matters. p.s. historically I have bought more Intel CPU's and NVIDIA GPU's but I have had some AMD CPU's and one AMD GPU.
    • Both of these companies as well as Qualcomm and Apple need competition. Otherwise, they just coast. I don't prefer macOS, though I like some of Apple's hardware, but if anyone needs competition, it is Apple. Their prices are already outrageous and they need to have a reason to produce good hardware and at least keep prices remotely reasonable. (It is criminal what they charge for RAM upgrades especially.) Qualcomm needs to push AMD and Intel not to be so sloppy with the performance/efficiency aspect. Granted, AMD has been doing quite well in this respect considering they are not an ARM architecture. I personally want to have more options that truly compete with Macbook Air and Macbook Pro's on the Windows side. It is difficult to achieve what Apple does since they control the entire stack and that is fundamentally different for Windows PCs other than maybe Microsoft Surface PCs.
  • Recent Achievements

    • Week One Done
      Hartej earned a badge
      Week One Done
    • One Year In
      TsunadeMama earned a badge
      One Year In
    • Week One Done
      shaheen earned a badge
      Week One Done
    • Dedicated
      Cole Multipass earned a badge
      Dedicated
    • Week One Done
      Alexander 001 earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      565
    2. 2
      +FloatingFatMan
      182
    3. 3
      ATLien_0
      175
    4. 4
      Skyfrog
      111
    5. 5
      Som
      106
  • Tell a friend

    Love Neowin? Tell a friend!