Together with a colleague, I’m giving basic .Net training for colleagues at this moment. Not at THIS moment exactly, because they’re doing exercises right now. But today is the second day of four days of training in total. Currently we already have two weird things popping up.

Last week we encountered significant inaccuracy when calculating values using doubles. For instance, when adding 0.1 to a double (instantiated at 0) several times, the value wondered off. After 3 or 4 times there was an inaccuracy of 2 or 3 in the last decimal. The difference is very very small, but it’s there… I knew there’s an inaccuracy in the representation of doubles, but I always thought it only occurred with difficult fractional values.

VB6 DLL’s are not always imported as you would expect. Visual Studio (2005) automatically generates interop assemblies when you reference a non .Net assembly. Today one of the course takers did this, which resulted in classes that didn’t have all the properties defined in the old DLL. There were two string properties having the exact same coding placed in different classes, and only one of them showed up in the interop assembly. Also, some properties showed up as properties, some showed up as methods (set_PropertyName()) and some of them didn’t show up at all. I’m currently investigating why, but it’s kind of weird…

Almost all values that can easily be represented using decimals (like 0.1, 0.2, 0.3, 0.15, etc.) cannot be represented exactly in binary notation with a finite number of digits. For computers the binary representation is the most efficient, so doubles are stored in binary representation.

For example, decimal fractions that can be represented accurately in binary notation are:

1 = 1/1 = (1)

0.5 = 1/2 = (0.1)

0.25 = 1/4 = (0.01)

0.125 = 1/8 = (0.001)

0.0625 = 1/16 = (0.0001)

0.03125 = 1/32 = (0.0001)

so

0.75 = 1/2 + 1/4 = (0.11)

An example of what you call “difficult fractional values” is

0.1 = 1/10 = 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + … = (0.000110011001100….)

If doubles were represented ternary, other numbers could be stored exactly:

0.33….. = 1/3 = [0.1]

0.66….. = 2/3 = [0.2]

And a difficult one is

0.5 = 1/2 = 1/3 + 1/9 + 1/27 + 1/81 + … = [0.111…]

I’ve used

x for decimal notation

(x) for binary notation

[x] for ternary notation

Check out http://en.wikipedia.org/wiki/Binary_numeral_system for much more detail.