all groups > dotnet academic > april 2005 >
You're in the

dotnet academic

group:

Math Error in the .NET Framework 1.1.4322 SP1


Math Error in the .NET Framework 1.1.4322 SP1 limelight
4/4/2005 12:21:03 PM
dotnet academic:
I have discovered a math error in the .NET framework's Log function. If you
use the overloaded method of System.Math.Log that allows you to specify the
base to which the logarithm should be taken, the result is off in at least
one instance. The problem here is actually seeing the error as it will not
occur at all if the application is run from within the IDE; it only happens
when the application is run from a command line. Secondly, the amount by
which the calculation is off is very small; even though the double data type
holds the errant value, it seems to round off when printed (via ToString())
and shows the correct one. The problem is that the errant value is still used
in further calculations, which can throw off some functions.

Specific example:

The function System.Math.Log(8,2) yields a value of 3 - 4x10^-16
(2.9999999999999996) instead of 3 when run from a command line (again, this
will not occur if run inside the IDE). You can store the result of this
computation in a double precision variable, but if you print the variable's
value to the console by calling its ToString() method, the output will be 3.
You can verify, however, that the value is indeed off by printing the result
of some calculations using it. To see this, use Visual Studio to create a new
C# console application and paste the following code sample in its "Main"
method:

---- Begin Code Sample ---

// try log function using the overloaded method that specifies the base
Console.WriteLine("Using System.Math.Log overload to specify desired
base...");
double log = System.Math.Log(8,2); // compute the log of 8 to the
base of 2 (should be 3, but will be 3 - 4x10^-16 when run from a command
prompt)
double floor = System.Math.Floor(log); // get the floor of the result
(should be 3, but will be 2 when run from a command prompt)
Console.WriteLine("Log2 8 = " + log.ToString()); // print the log of 8 to
the base of 2
Console.WriteLine("Floor(Log2 8) = " + floor.ToString()); // print the
floor of the result
Console.WriteLine("Log2 8 == 3? : " + ((bool) (log == 3)).ToString()); //
print whether the log of 8 to the base of 2 is equal to 3 (should be true,
but will be false when run from a command prompt)

Console.WriteLine();

// try the log function while doing things the "manual" way
Console.WriteLine("Using Log x / Log y method of computing the same
logarithm...");
log = System.Math.Log(8) / System.Math.Log(2); // compute the log of 8 to
the base of 2 (will be 3)
floor = System.Math.Floor(log); // get the floor of the result (will
be 3)
Console.WriteLine("Log2 8 = " + log.ToString()); // print the log of 8 to
the base of 2 computed via Log x / Log y
Console.WriteLine("Floor(Log2 8) = " + floor.ToString()); // print the
floor of the result
Console.WriteLine("Log2 8 == 3? : " + ((bool) (log == 3)).ToString()); //
print whether the log of 8 to the base of 2 is equal to 3 (will be true)

Console.Read();

--- End Code Sample ---


Note that when you calculate the "manual" way (log x / log y) then the
calculation is correct. In theory, the framework should be doing exactly this
internally, so why it is off is a mystery.

You can see the actual value of the log function by putting a statement
such as "Console.Read()" as your first line so you have a way to get the
program to stop. Compile the program and run it from the command line. Open a
new instance of Visual Studio and click on Tools > Debug Processes and select
the application. Once you have attached the debugger, break the application
and start stepping through the code. Add the variable "log" to your watch
window and you will see its value is 3 - 4x10^-16, not 3 when computed using
System.Math.Log(8,2). These steps must be taken as the problem will not occur
if you initially start the program within the IDE.

Has anyone else experienced this? I would be interested to know if the
Re: Math Error in the .NET Framework 1.1.4322 SP1 Brian Hetrick
4/4/2005 10:56:12 PM
"limelight" wrote ...
[quoted text, click to view]

I confirm this behavior with VS .NET 2003 and .NET Framework 1.1.4322
SP1, including it occuring with command line and not occurring when
debugging via VS.

[quoted text, click to view]

Dividing log x by log y is /a/ way of getting log base y of x, not
/the/ way.

The difference is 1 LSB (the "wrong" value is 4007FFFFFFFFFFFF, the
"right" value is 4008000000000000), so I think being concerned about
the accuracy is probably futile. It does concern me, however, that
the answer depends on whether the program is run in the IDE or from
the command line.
Re: Math Error in the .NET Framework 1.1.4322 SP1 limelight
4/5/2005 8:43:06 AM
[quoted text, click to view]

Actually, if you use ILDASM to look at mscorlib.dll, you will find that
the overloaded function System.Math.Log(double a, double newBase) actually
calls System.Math.Log(double d) twice. Internally, it does take log x / log
y, which actually makes this even more puzzling as doing that yourself works.

[quoted text, click to view]

In my case, the difference is everything. If you are using the bits of an
integer as an array of boolean values (needed given the algorithm that I am
running) then this calculation is a nightmare. In the calculation, you take
the log of the value and pass it to the floor function to get the set bit. In
the given example, the set bit is actually the 3rd, but the calculation will
give you the 2nd.

There are also other powers of 2 that are off. The odd thing here is that
certain powers are off when run from within the IDE and different ones are
off when run from the command line. I computed the first 64 powers of 2 and
confirmed that 9 of them are off when run inside the IDE. There are 12 powers
of 2 that are off if run from the command line. Other than 51, 55 and 59, all
of the powers are different depending on whether you run the program inside
the IDE or outside of it. Try the following code:

for(int i = 1;i < 64;i++)
{
if(System.Math.Log(System.Math.Pow(2,i),2) != i)
Console.WriteLine(i.ToString());
}

Also, I tried this same calculation using log x / log y and found that 9
powers of 2 are off, but they are different than the ones that are off using
the overloaded method. Additionally, these are the same whether run inside
the IDE or outside of it.

Lastly, I used VB 6.0 to compute these first 64 powers of 2 and it
checked out fine. It's unsettling to me that VB 6.0 can get it right, but
Re: Math Error in the .NET Framework 1.1.4322 SP1 Brian Hetrick
4/7/2005 8:08:30 AM
"limelight" wrote ...
[quoted text, click to view]

If you know the answer is an integer, why aren't you rounding to the
nearest integer instead of assuming that any error will be positive?
Floating point computations are not exact. Add .5, take the floor,
and be done with it. But if you're starting out with an integer and
figuring out which one bit is set, I suspect evaluating two
transcendentals is just about a pessimal way of doing it.

[quoted text, click to view]

To me, that is the scary part.
RE: Math Error in the .NET Framework 1.1.4322 SP1 Hannibal
4/16/2005 12:41:03 PM


[quoted text, click to view]

I'm sure you guys already thought of this, and maybe I'm totally off track.
Microsoft may have made a mistake in that, in the instance of VS.NET, they
aren't using the correct equation for this closed-form condition. For
example,

3^lgn is a fractal and is the limiting case as n diverges to infinity, lgn
being the recursively defined dimension. If used in this form the series will
continue to be summed until truncated because of the infinite perimeter of
the geometrical figure.

By the properties of logarithms, 3^lgn can be converted to n^lg3 which will
sum the series and give a finite answer in terms of the figure's area, lg3
being the Haussendorf (not sure if i spelled his name right =x) dimension.

In terms of a geometrical figure, the structure of each of the parts,
represented by 3^lgn, and and the whole represented by n^lg3, are
"self-similar," in that they are identical except for their scale.

Maybe Microsoft is ignoring this fact and using the wrong equation (in which
chaos occurs), or they meant to use the equation, but aren't compensating for
it.

Pardon me if I am totally missing the point, or misunderstood what you mean
to calculate, in which case you can happily ignore this =].

AddThis Social Bookmark Button