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