By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,480 Members | 1,164 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,480 IT Pros & Developers. It's quick & easy.

Once again Math.Log

P: n/a
I've found the discussion about Math.Log and the error with

Math.Log(8,2)

on Google. Unfortunatly the full thread isn't on my news server, so I
can't reply.

The problem doesn't only depend on representation of floating numbers.
When You execute

int res = (int)Math.Log(8, 2);
if (res == 3)
{
Console.WriteLine("right");
}
else
{
Console.WriteLine("false");
}

You get the output "false". My first thoughts also where to the floating
representation. But if You debug the same lines of Code, the debugger
steps to the output of "right", the result res is "3".
Does the debugger use another Math-engine?

--
Sleepless in Berlin
Wernfried
Nov 16 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Wernfried Schwenkner <we*************************@sesa.de> wrote:
I've found the discussion about Math.Log and the error with

Math.Log(8,2)

on Google. Unfortunatly the full thread isn't on my news server, so I
can't reply.

The problem doesn't only depend on representation of floating numbers.
When You execute

int res = (int)Math.Log(8, 2);
if (res == 3)
{
Console.WriteLine("right");
}
else
{
Console.WriteLine("false");
}

You get the output "false". My first thoughts also where to the floating
representation. But if You debug the same lines of Code, the debugger
steps to the output of "right", the result res is "3".

Does the debugger use another Math-engine?


No - it's just it's formatting something "very close to 3" as "3".

Personally I never trust the debugger for that kind of thing - nor even
the built-in ToString methods. If you want to really see *exactly* what
value is in a double, use something like my DoubleConverter class:

http://www.pobox.com/~skeet/csharp/DoubleConverter.cs

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #2

P: n/a
Jon Skeet [C# MVP] <sk***@pobox.com> wrote in
news:MP************************@msnews.microsoft.c om:
Wernfried Schwenkner <we*************************@sesa.de> wrote:
I've found the discussion about Math.Log and the error with
<snip> You get the output "false". My first thoughts also where to the
floating representation. But if You debug the same lines of Code, the
debugger steps to the output of "right", the result res is "3".

Does the debugger use another Math-engine?


No - it's just it's formatting something "very close to 3" as "3".

<snip>

I think his point is that when he runs the program without debugging, res
is not 3, but with debugging res is 3, ie. the program take different
routes.

And he's exactly right:

reproduce:
1. create a new winforms project in VS.NET 2003
2. add a single button to the form, double-click to add event handler
3. type in the following code:

Int32 i = (Int32)Math.Log(8, 2);
if (i == 3)
Text = "i == 3";
else
Text = "i != 3";

4. run program with Ctrl-F5 to start without debugger, click button,
caption of window becomes i != 3, close program
5. run program with F5 to start with debugger, click button, caption of
window becomes i == 3

This means that the result of that cast, or the log operation, differs
wether you use the debugger or not. Perhaps there's some slight
differences in the debug binaries of the .net runtime ?
--
Lasse Vågsæther Karlsen
la***@vkarlsen.no
PGP KeyID: 0x0270466B
Nov 16 '05 #3

P: n/a
Lasse Vågsæther Karlsen <la***@vkarlsen.no> wrote:
Does the debugger use another Math-engine?
No - it's just it's formatting something "very close to 3" as "3".

<snip>

I think his point is that when he runs the program without debugging, res
is not 3, but with debugging res is 3, ie. the program take different
routes.


Ah - oops. Misread :(
And he's exactly right:

reproduce:
1. create a new winforms project in VS.NET 2003
2. add a single button to the form, double-click to add event handler
3. type in the following code:

Int32 i = (Int32)Math.Log(8, 2);
if (i == 3)
Text = "i == 3";
else
Text = "i != 3";

4. run program with Ctrl-F5 to start without debugger, click button,
caption of window becomes i != 3, close program
5. run program with F5 to start with debugger, click button, caption of
window becomes i == 3

This means that the result of that cast, or the log operation, differs
wether you use the debugger or not. Perhaps there's some slight
differences in the debug binaries of the .net runtime ?


Hmm... not sure. Certainly seems very odd.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #4

P: n/a
Yep, the JIT compiler works a little different for executables that have
been started in the debugger. (attaching the debugger to an already running
executable doesn't change anything). For example, it doesn't inline function
calls, so you can always step into functions.
My guess is that an inlined version of Math.Log (outside the debugger) can
keep all internal results in 80-bit FPU registers, while a non-inlined
version has to return them as 64-bit double values, which leads to different
results.

i.e. if Log is defined like this:
public static double Log(double a, double newBase)
{
return (Math.Log(a)/Math.Log(newBase));
}

If Math.Log(a) and Math.Log(newBase) are inlined, the results of the calls
may stay in FPU registers (which are 80 bit long). On the other hand, if
they are not inlined, the results have to be returned as 64-bit-doubles.
That explains the loss of precision.

Niki
"Lasse Vågsæther Karlsen" <la***@vkarlsen.no> wrote in
news:Xn*****************************@207.46.248.16 ...
Jon Skeet [C# MVP] <sk***@pobox.com> wrote in
news:MP************************@msnews.microsoft.c om:
Wernfried Schwenkner <we*************************@sesa.de> wrote:
I've found the discussion about Math.Log and the error with
<snip> You get the output "false". My first thoughts also where to the
floating representation. But if You debug the same lines of Code, the
debugger steps to the output of "right", the result res is "3".

Does the debugger use another Math-engine?


No - it's just it's formatting something "very close to 3" as "3".

<snip>

I think his point is that when he runs the program without debugging, res
is not 3, but with debugging res is 3, ie. the program take different
routes.

And he's exactly right:

reproduce:
1. create a new winforms project in VS.NET 2003
2. add a single button to the form, double-click to add event handler
3. type in the following code:

Int32 i = (Int32)Math.Log(8, 2);
if (i == 3)
Text = "i == 3";
else
Text = "i != 3";

4. run program with Ctrl-F5 to start without debugger, click button,
caption of window becomes i != 3, close program
5. run program with F5 to start with debugger, click button, caption of
window becomes i == 3

This means that the result of that cast, or the log operation, differs
wether you use the debugger or not. Perhaps there's some slight
differences in the debug binaries of the .net runtime ?
--
Lasse Vågsæther Karlsen
la***@vkarlsen.no
PGP KeyID: 0x0270466B

Nov 16 '05 #5

P: n/a

"Niki Estner" <ni*********@cube.net> wrote in message
news:Od*************@tk2msftngp13.phx.gbl...
Yep, the JIT compiler works a little different for executables that have
been started in the debugger. (attaching the debugger to an already running executable doesn't change anything). For example, it doesn't inline function calls, so you can always step into functions.
My guess is that an inlined version of Math.Log (outside the debugger) can
keep all internal results in 80-bit FPU registers, while a non-inlined
version has to return them as 64-bit double values, which leads to different results.

i.e. if Log is defined like this:
public static double Log(double a, double newBase)
{
return (Math.Log(a)/Math.Log(newBase));
}

If Math.Log(a) and Math.Log(newBase) are inlined, the results of the calls
may stay in FPU registers (which are 80 bit long). On the other hand, if
they are not inlined, the results have to be returned as 64-bit-doubles.
That explains the loss of precision.
Agreed, and to back up your suppostion, from the Tool Developer's Guide,
section 11.1.3:

"Storage locations for floating point numbers (statics, array elements, and
fields of classes) are of fixed size. The supported storage sizes are
float32 and float64. Everywhere else (on the evaluation stack, as arguments,
as return types, and as local variables) floating point numbers are
represented using an internal floating-point type. In each such instance,
the nominal type of the variable or expression is either R4 or R8, but its
value may be represented internally with additional range and/or precision.
The size of the internal floating-point representation is
implementation-dependent, may vary, and shall have precision at least as
great as that of the variable or expression being represented. "

and furthermore:

"Note: The use of an internal representation that is wider than float32 or
float64 may cause differences in computational results when a developer
makes seemingly unrelated modifications to their code, the result of which
may be that a value is spilled from the internal representation (e.g. in a
register) to a location on the stack. "

Stu

Niki
"Lasse Vågsæther Karlsen" <la***@vkarlsen.no> wrote in
news:Xn*****************************@207.46.248.16 ...
Jon Skeet [C# MVP] <sk***@pobox.com> wrote in
news:MP************************@msnews.microsoft.c om:
Wernfried Schwenkner <we*************************@sesa.de> wrote:
> I've found the discussion about Math.Log and the error with
>

<snip>
> You get the output "false". My first thoughts also where to the
> floating representation. But if You debug the same lines of Code, the
> debugger steps to the output of "right", the result res is "3".
>
> Does the debugger use another Math-engine?

No - it's just it's formatting something "very close to 3" as "3".

<snip>

I think his point is that when he runs the program without debugging, res is not 3, but with debugging res is 3, ie. the program take different
routes.

And he's exactly right:

reproduce:
1. create a new winforms project in VS.NET 2003
2. add a single button to the form, double-click to add event handler
3. type in the following code:

Int32 i = (Int32)Math.Log(8, 2);
if (i == 3)
Text = "i == 3";
else
Text = "i != 3";

4. run program with Ctrl-F5 to start without debugger, click button,
caption of window becomes i != 3, close program
5. run program with F5 to start with debugger, click button, caption of
window becomes i == 3

This means that the result of that cast, or the log operation, differs
wether you use the debugger or not. Perhaps there's some slight
differences in the debug binaries of the .net runtime ?
--
Lasse Vågsæther Karlsen
la***@vkarlsen.no
PGP KeyID: 0x0270466B


Nov 16 '05 #6

P: n/a
"Stu Smith" <st*****@nospam-digita.com> wrote in
news:eg*************@TK2MSFTNGP11.phx.gbl:

<snip>
"Note: The use of an internal representation that is wider than
float32 or float64 may cause differences in computational results when
a developer makes seemingly unrelated modifications to their code, the
result of which may be that a value is spilled from the internal
representation (e.g. in a register) to a location on the stack. "

<snip>

Nice explanation. It makes sense, just didn't think about this when I
looked at the original post.

I can see this as the source for future discussions like "what's the point
of using the debugger if the code behaves different" but anyone wanting to
use that point please bear in mind that the original post was about a cast
to Int32 from a double, relying on the floating point value to be exactly
like 3, and anyone that knows anything about floating point numbers knows
that the likelihood of that is 50/50, and there's only a 10% chance of
that.

:)

--
Lasse Vågsæther Karlsen
la***@vkarlsen.no
PGP KeyID: 0x0270466B
Nov 16 '05 #7

P: n/a
In article <Xn*****************************@207.46.248.16>,
la***@vkarlsen.no says...
I can see this as the source for future discussions like "what's the point
of using the debugger if the code behaves different" but anyone wanting to
use that point please bear in mind that the original post was about a cast
to Int32 from a double, relying on the floating point value to be exactly
like 3, and anyone that knows anything about floating point numbers knows
that the likelihood of that is 50/50, and there's only a 10% chance of
that.


No, my post was not a question relying on floating point values. I know
the floating point representaion very well (wrote floating point
routines in assembler myself without having a FPP). My problem was the
different behaviour in debug and release mode. So the answers could
clearify all.
--
Sleepless in Berlin
Wernfried
Nov 16 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.