Meaning of Double.Epsilon

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • cody

    #16
    Re: Meaning of Double.Epsilon

    Damn. Errata:

    NaN cannot be used to test for is-not-a-number anyway. You *have to* use
    IsNaN instead.
    The same is true for NegativeInfinit y and PositiveInfinit y.

    --
    cody

    Freeware Tools, Games and Humour
    http://www.deutronium.de.vu || http://www.deutronium.tk
    "cody" <no_spam_deutro nium@gmx.net> schrieb im Newsbeitrag
    news:#LxFkoXlEH A.3476@tk2msftn gp13.phx.gbl...[color=blue]
    > I tend to say that operators == result is undefined for floating point[/color]
    types[color=blue]
    > (except decimal).
    > You never know how variables are stored in memory. testing for equality[/color]
    for[color=blue]
    > a floating point variables never makes sense, even if you do:
    >
    > float a = 1f;
    > float b = 1f;
    > if (a==b) { }
    >
    > The Jitter may choose to place a and b in difference register types (32,[/color]
    64[color=blue]
    > or 80 bits), so a==b may return true or false depending on the machine[/color]
    type,[color=blue]
    > framework version, debug or release settings or if a debugger is attached[/color]
    or[color=blue]
    > in which way the variables are used in code or wheather the method is
    > inlined or not.
    >
    > So it would be great if the compiler would at least issue a warning if it
    > spots code which tests for equality with floating point values.
    >
    > The only thing I could imagine is testing for NaN but in that case one
    > should use IsNaN() methods of struct Double and Single.
    >
    > --
    > cody
    >
    > Freeware Tools, Games and Humour
    > http://www.deutronium.de.vu || http://www.deutronium.tk
    > "Jon Skeet [C# MVP]" <skeet@pobox.co m> schrieb im Newsbeitrag
    > news:MPG.1ba815 e2cc7c8ef698b35 e@msnews.micros oft.com...[color=green]
    > > Niki Estner <niki.estner@cu be.net> wrote:[color=darkred]
    > > > > It's the last step that I'm not sure about though - is it possible[/color][/color][/color]
    for[color=blue][color=green][color=darkred]
    > > > > a and b to be different, but their difference to be so close to 0 as[/color][/color]
    > to[color=green][color=darkred]
    > > > > be unrepresentably small? It feels unlikely, but I know that[/color][/color][/color]
    intuition[color=blue][color=green][color=darkred]
    > > > > is often horribly flawed when it comes to floating point maths.
    > > >
    > > > I guess it's possible if a and b are stored in 80-bit FPU registers:[/color][/color][/color]
    b-a[color=blue]
    > (80[color=green][color=darkred]
    > > > bit) could still be different form 0 (using an 80-bit comparison), but[/color][/color]
    > the[color=green][color=darkred]
    > > > difference would be smaller than double.Epsilon. Also Math.Abs(b-a)[/color][/color]
    > would[color=green][color=darkred]
    > > > actually return 0 (if not inlined) as b-a would get casted to a[/color][/color][/color]
    (64-bit)[color=blue][color=green][color=darkred]
    > > > double value.[/color]
    > >
    > > Aargh, yes. I knew there was a good reason to be hesitant :)
    > >[color=darkred]
    > > > Sample code (compares (double.Epsilon/2) with 0):[/color]
    > >
    > > <snip>
    > >
    > > Good, thanks. Here's something interesting, based on your code:
    > >
    > > using System;
    > > public class MyClass
    > > {
    > > public static void Main()
    > > {
    > > double two = double.Parse("2 ");
    > > double a = double.Epsilon/two;
    > > double b = 0;
    > > Console.WriteLi ne(a==b);
    > > Console.WriteLi ne(Math.Abs(b-a) < double.Epsilon) ;
    > > }
    > > }
    > >
    > > That prints out (on my box):
    > > True
    > > True
    > >
    > > If you comment out the last line, however, it just prints out
    > > False
    > >
    > > Presumably the call to Math.Abs forces a and b to be "normal" 64-bit
    > > values rather than just 80-bit registers, or something like that.
    > >
    > > --
    > > Jon Skeet - <skeet@pobox.co m>
    > > http://www.pobox.com/~skeet
    > > If replying to the group, please do not mail me too[/color]
    >
    >[/color]


    Comment

    • Niki Estner

      #17
      Re: Meaning of Double.Epsilon


      "cody" <no_spam_deutro nium@gmx.net> schrieb im Newsbeitrag
      news:%23LxFkoXl EHA.3476@tk2msf tngp13.phx.gbl. ..[color=blue]
      >I tend to say that operators == result is undefined for floating point
      >types
      > (except decimal).
      > You never know how variables are stored in memory.[/color]

      Of course you do. The *memory* size is determined by the variable's type.
      [color=blue]
      > testing for equality for
      > a floating point variables never makes sense, even if you do:
      >
      > float a = 1f;
      > float b = 1f;
      > if (a==b) { }
      >
      > The Jitter may choose to place a and b in difference register types (32,
      > 64
      > or 80 bits), so a==b may return true or false depending on the machine
      > type,
      > framework version, debug or release settings or if a debugger is attached
      > or
      > in which way the variables are used in code or wheather the method is
      > inlined or not.[/color]

      No, I'm pretty sure (a==b) will always be true here: AFAIK it's guaranteed
      that converting a 32-bit floating point value to 64 bit or 80 bit will never
      cause any loss in precision; Also, you're guaranteed that a 64-bit value
      will never be stored in a 32-bit or smaller register (note that intel FPU's
      don't have 32-bit or 64-bit registers anyway). So, in the case of constants
      the '==' operator should always work correctly.
      [color=blue]
      > So it would be great if the compiler would at least issue a warning if it
      > spots code which tests for equality with floating point values.[/color]

      It's common to test a floating point value for some constant it's
      initialized to (like: if (a == 0) a = GetSomeValue(); ). Other tests for
      common values (e.g. double.Parse(st r) == 1) will work, too.
      A warning wouldn't hurt (if it can be turned off), but I would prefer a
      special "about equal" operator with fuzzy comparison rules.

      Niki


      Comment

      • Jon Skeet [C# MVP]

        #18
        Re: Meaning of Double.Epsilon

        Niki Estner <niki.estner@cu be.net> wrote:[color=blue][color=green]
        > > So it would be great if the compiler would at least issue a warning if it
        > > spots code which tests for equality with floating point values.[/color]
        >
        > It's common to test a floating point value for some constant it's
        > initialized to (like: if (a == 0) a = GetSomeValue(); ). Other tests for
        > common values (e.g. double.Parse(st r) == 1) will work, too.
        > A warning wouldn't hurt (if it can be turned off), but I would prefer a
        > special "about equal" operator with fuzzy comparison rules.[/color]

        I don't think I'd want an operator, but a utility method on Double
        wouldn't hurt. It could either take the two values and the "fuzziness
        factor", or there could perhaps be a default fuzziness factor which
        could be changed programatically .

        --
        Jon Skeet - <skeet@pobox.co m>
        Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

        If replying to the group, please do not mail me too

        Comment

        • cody

          #19
          Re: Meaning of Double.Epsilon

          > >I tend to say that operators == result is undefined for floating point[color=blue][color=green]
          > >types
          > > (except decimal).
          > > You never know how variables are stored in memory.[/color]
          >
          > Of course you do. The *memory* size is determined by the variable's type.[/color]

          Yes in memory, but you do not know which CPU registers will be used.
          [color=blue]
          > No, I'm pretty sure (a==b) will always be true here: AFAIK it's guaranteed
          > that converting a 32-bit floating point value to 64 bit or 80 bit will[/color]
          never[color=blue]
          > cause any loss in precision;[/color]

          Maybe not precision but it will not be exactly the same value.
          The following program outputs "true true false false" on my machine:

          double d=0.0;
          float f=0.0f;
          double d1=1.0;
          float f1=1.0f;
          double d2=1.3;
          float f2=1.3f;
          float f3=float.Parse( "0.2");
          float f4=0.2f;
          MessageBox.Show (string.Format( "{0} {1} {2} {3}", d==f, d1==f1, d2==f2,
          f3==f4));
          [color=blue]
          > Also, you're guaranteed that a 64-bit value
          > will never be stored in a 32-bit or smaller register[/color]

          Thats clear. It it only guaranteed that a variable size 32 bit will be
          stored in a register with *at least* 32 bit or more.

          So, in the case of constants the '==' operator should always work
          correctly.

          It won't see above.
          [color=blue]
          > It's common to test a floating point value for some constant it's
          > initialized to (like: if (a == 0) a = GetSomeValue(); ). Other tests for
          > common values (e.g. double.Parse(st r) == 1) will work, too.[/color]

          If you are lucky it will work on some machines with some values.
          [color=blue]
          > A warning wouldn't hurt (if it can be turned off), but I would prefer a
          > special "about equal" operator with fuzzy comparison rules.[/color]

          I'd vote against it. Testing equality is always bad idea anyway. Even if,
          there must be a possibility to specify the tolerance value because the
          fuzzyness really depends on the application. The method wouldn't do anything
          else but Math.Abs(a,b)<T olerance so there is very little point for including
          such a method in the framework.

          --
          cody

          Freeware Tools, Games and Humour
          http://www.deutronium.de.vu || http://www.deutronium.tk


          Comment

          • Niki Estner

            #20
            Re: Meaning of Double.Epsilon

            "cody" <no_spam_deutro nium@gmx.net> wrote in
            news:ucHoVCZlEH A.596@TK2MSFTNG P11.phx.gbl...[color=blue]
            >...
            > Maybe not precision but it will not be exactly the same value.
            > The following program outputs "true true false false" on my machine:
            >
            > double d=0.0;
            > float f=0.0f;
            > double d1=1.0;
            > float f1=1.0f;
            > double d2=1.3;
            > float f2=1.3f;
            > float f3=float.Parse( "0.2");
            > float f4=0.2f;
            > MessageBox.Show (string.Format( "{0} {1} {2} {3}", d==f, d1==f1, d2==f2,
            > f3==f4));
            > ...[/color]

            The point is that
            float a=1.3f;
            double b=1.3f;
            Console.WriteLi ne(a==b);
            Will always return true, because converting "1.3f" (or any other 32-bit
            float-value) to double will not change it; Of course this value can actually
            be different from "1.3d".

            Your original example was:
            float a = 1f;
            float b = 1f;
            if (a==b) { }

            As shown above, "1f" (or any other float constant) will not be changed when
            converted to a double (or 80-bit fp value), so that kind of comparison *is*
            safe.

            Niki


            Comment

            • Jeremy Davis

              #21
              Re: Meaning of Double.Epsilon

              "cody" wrote:
              [color=blue][color=green][color=darkred]
              > > >I tend to say that operators == result is undefined for floating point
              > > >types
              > > > (except decimal).
              > > > You never know how variables are stored in memory.[/color]
              > >
              > > Of course you do. The *memory* size is determined by the variable's type.[/color]
              >
              > Yes in memory, but you do not know which CPU registers will be used.
              >[color=green]
              > > No, I'm pretty sure (a==b) will always be true here: AFAIK it's guaranteed
              > > that converting a 32-bit floating point value to 64 bit or 80 bit will[/color]
              > never[color=green]
              > > cause any loss in precision;[/color]
              >
              > Maybe not precision but it will not be exactly the same value.
              > The following program outputs "true true false false" on my machine:
              >
              > double d=0.0;
              > float f=0.0f;
              > double d1=1.0;
              > float f1=1.0f;
              > double d2=1.3;
              > float f2=1.3f;
              > float f3=float.Parse( "0.2");
              > float f4=0.2f;
              > MessageBox.Show (string.Format( "{0} {1} {2} {3}", d==f, d1==f1, d2==f2,
              > f3==f4));
              >[color=green]
              > > Also, you're guaranteed that a 64-bit value
              > > will never be stored in a 32-bit or smaller register[/color]
              >
              > Thats clear. It it only guaranteed that a variable size 32 bit will be
              > stored in a register with *at least* 32 bit or more.
              >
              > So, in the case of constants the '==' operator should always work
              > correctly.
              >
              > It won't see above.
              >[color=green]
              > > It's common to test a floating point value for some constant it's
              > > initialized to (like: if (a == 0) a = GetSomeValue(); ). Other tests for
              > > common values (e.g. double.Parse(st r) == 1) will work, too.[/color]
              >
              > If you are lucky it will work on some machines with some values.
              >[color=green]
              > > A warning wouldn't hurt (if it can be turned off), but I would prefer a
              > > special "about equal" operator with fuzzy comparison rules.[/color]
              >
              > I'd vote against it. Testing equality is always bad idea anyway. Even if,
              > there must be a possibility to specify the tolerance value because the
              > fuzzyness really depends on the application. The method wouldn't do anything
              > else but Math.Abs(a,b)<T olerance so there is very little point for including
              > such a method in the framework.
              >
              > --
              > cody
              >
              > Freeware Tools, Games and Humour
              > http://www.deutronium.de.vu || http://www.deutronium.tk[/color]

              Equality comparison between integers (within the range and precision of your
              chosen data type) and rational numbers of the form x/(2^y) ought to always
              work. Other than that, you get into the ugliness of trying to losslessly
              convert non-integral values between bases. (We all know how fun it is to
              write out 1/3 as an "exact" decimal.)

              Comment

              • cody

                #22
                Re: Meaning of Double.Epsilon

                > > Maybe not precision but it will not be exactly the same value.[color=blue][color=green]
                > > The following program outputs "true true false false" on my machine:
                > >
                > > double d=0.0;
                > > float f=0.0f;
                > > double d1=1.0;
                > > float f1=1.0f;
                > > double d2=1.3;
                > > float f2=1.3f;
                > > float f3=float.Parse( "0.2");
                > > float f4=0.2f;
                > > MessageBox.Show (string.Format( "{0} {1} {2} {3}", d==f, d1==f1, d2==f2,
                > > f3==f4));
                > > ...[/color]
                >
                > The point is that
                > float a=1.3f;
                > double b=1.3f;
                > Console.WriteLi ne(a==b);
                > Will always return true, because converting "1.3f" (or any other 32-bit
                > float-value) to double will not change it; Of course this value can[/color]
                actually[color=blue]
                > be different from "1.3d".[/color]

                But the comparison returned FALSE! Did you read my posting?
                [color=blue]
                > Your original example was:
                > float a = 1f;
                > float b = 1f;
                > if (a==b) { }
                >
                > As shown above, "1f" (or any other float constant) will not be changed[/color]
                when[color=blue]
                > converted to a double (or 80-bit fp value), so that kind of comparison[/color]
                *is*[color=blue]
                > safe.[/color]

                This could cause the same problem as my first example. I can remember that
                soem time ago someone gave me an example of values which really were
                difference although there were both float and originally the same constant
                was assigned to them.

                --
                cody

                Freeware Tools, Games and Humour
                http://www.deutronium.de.vu || http://www.deutronium.tk


                Comment

                • Niki Estner

                  #23
                  Re: Meaning of Double.Epsilon

                  "cody" <no_spam_deutro nium@gmx.net> wrote in
                  news:%23rsH1lbl EHA.1356@TK2MSF TNGP09.phx.gbl. ..[color=blue]
                  > ...
                  > But the comparison returned FALSE! Did you read my posting?[/color]

                  Cody, please! Correct your code to:

                  double d=0.0f;
                  float f=0.0f;
                  double d1=1.0f;
                  float f1=1.0f;
                  double d2=1.3f;
                  float f2=1.3f;
                  float f3=float.Parse( "0.2");
                  float f4=0.2f;

                  Because that's what we've been talking about: converting a 32-bit float to a
                  64-bit float won't change it's value.
                  So, it's always safe to compare a 32-bit float with another 32-bit float,
                  even if the JITer chooses to put it in a 80-bit FPU register.
                  [color=blue][color=green]
                  >> Your original example was:
                  >> float a = 1f;
                  >> float b = 1f;
                  >> if (a==b) { }
                  >>
                  >> As shown above, "1f" (or any other float constant) will not be changed[/color]
                  > when[color=green]
                  >> converted to a double (or 80-bit fp value), so that kind of comparison[/color]
                  > *is*[color=green]
                  >> safe.[/color]
                  >
                  > This could cause the same problem as my first example. I can remember that
                  > soem time ago someone gave me an example of values which really were
                  > difference although there were both float and originally the same constant
                  > was assigned to them.[/color]

                  So, why don't you show that example?

                  Look, a 32-bit FP number has 1 sign bit, 8 bits exponent and 23 mantissa
                  bits.
                  A 64-bit FP number has 1 sign bit, 11 bits for the exponent, and 52 bits for
                  the mantissa part.
                  If you convert a 32-bit fp to a 64-bit fp number, all you have to do is
                  "append zeros" to the mantissa part, which doesn't change it's value, and
                  convert the exponent from 8 to 11 bits (which doesn't change it either). So,
                  how do you think something like this
                  float f1 = SomeValue;
                  Console.Writeli ne(f1 == (double)f1);
                  could ever return false (unless SomeValue was NaN, of course)?

                  Niki


                  Comment

                  • cody

                    #24
                    Re: Meaning of Double.Epsilon

                    > > But the comparison returned FALSE! Did you read my posting?[color=blue]
                    >
                    > Cody, please! Correct your code to:
                    >[/color]
                    [..][color=blue]
                    > double d2=1.3f;
                    > float f2=1.3f;[/color]
                    [..]


                    Damn you are right.. A very subtle difference. Now I understand. 1.3 is not
                    equal to 1.3f, but 1.3f is always 1.3f, no matter if it is put into a float
                    or double variable or stored in a 64 or 80 bit register.
                    [color=blue]
                    > Look, a 32-bit FP number has 1 sign bit, 8 bits exponent and 23 mantissa
                    > bits.
                    > A 64-bit FP number has 1 sign bit, 11 bits for the exponent, and 52 bits[/color]
                    for[color=blue]
                    > the mantissa part.
                    > If you convert a 32-bit fp to a 64-bit fp number, all you have to do is
                    > "append zeros" to the mantissa part, which doesn't change it's value, and
                    > convert the exponent from 8 to 11 bits (which doesn't change it either).[/color]

                    Very interesting information.

                    But I could swear I read somewhere that the register will affect the
                    comparison :)

                    --
                    cody

                    [Freeware, Games and Humor]
                    www.deutronium.de.vu || www.deutronium.tk


                    Comment

                    • Jon Skeet [C# MVP]

                      #25
                      Re: Meaning of Double.Epsilon

                      cody <please_dont.sp am.deutronium@g mx.de> wrote:[color=blue][color=green]
                      > > If you convert a 32-bit fp to a 64-bit fp number, all you have to do is
                      > > "append zeros" to the mantissa part, which doesn't change it's value, and
                      > > convert the exponent from 8 to 11 bits (which doesn't change it either).[/color]
                      >
                      > Very interesting information.
                      >
                      > But I could swear I read somewhere that the register will affect the
                      > comparison :)[/color]

                      It can if the conversion goes the other way - if a register holds an 80
                      bit number and that's converted to a 64 bit number.

                      Here's an example which actually didn't show up the problem on your box
                      last time I posted it, but it does show it on mine:

                      using System;

                      class Test
                      {
                      static float member;

                      static void Main()
                      {
                      member = Calc();
                      float local = Calc();
                      Console.WriteLi ne(local==membe r);
                      }

                      static float Calc()
                      {
                      float d1 = 2.82323f;
                      float d2 = 2.3f;
                      return d1*d2;
                      }
                      }

                      The member variable is strictly 32 bits, but the local variable can be
                      enregistered - so it ends up being more accurate than the member
                      variable, and the comparison fails (on my box).

                      --
                      Jon Skeet - <skeet@pobox.co m>
                      Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                      If replying to the group, please do not mail me too

                      Comment

                      • cody

                        #26
                        Re: Meaning of Double.Epsilon

                        > > > If you convert a 32-bit fp to a 64-bit fp number, all you have to do
                        is[color=blue][color=green][color=darkred]
                        > > > "append zeros" to the mantissa part, which doesn't change it's value,[/color][/color][/color]
                        and[color=blue][color=green][color=darkred]
                        > > > convert the exponent from 8 to 11 bits (which doesn't change it[/color][/color][/color]
                        either).[color=blue][color=green]
                        > >
                        > > Very interesting information.
                        > >
                        > > But I could swear I read somewhere that the register will affect the
                        > > comparison :)[/color]
                        >
                        > It can if the conversion goes the other way - if a register holds an 80
                        > bit number and that's converted to a 64 bit number.
                        >
                        > Here's an example which actually didn't show up the problem on your box
                        > last time I posted it, but it does show it on mine:
                        >
                        > using System;
                        >
                        > class Test
                        > {
                        > static float member;
                        >
                        > static void Main()
                        > {
                        > member = Calc();
                        > float local = Calc();
                        > Console.WriteLi ne(local==membe r);
                        > }
                        >
                        > static float Calc()
                        > {
                        > float d1 = 2.82323f;
                        > float d2 = 2.3f;
                        > return d1*d2;
                        > }
                        > }
                        >
                        > The member variable is strictly 32 bits, but the local variable can be
                        > enregistered - so it ends up being more accurate than the member
                        > variable, and the comparison fails (on my box).[/color]


                        Now I remember it was you with the example. But I still do not get it.
                        The explanation given by Niki seemed logical.
                        So if we never know which variable is put in which register so we can never
                        rely on that a comparison of two floating point variables will succeed?
                        So it stands as it is: Equality testing with floating point variables is
                        never a good idea because the result is undefined.

                        --
                        cody

                        Freeware Tools, Games and Humour
                        http://www.deutronium.de.vu || http://www.deutronium.tk


                        Comment

                        • Jon Skeet [C# MVP]

                          #27
                          Re: Meaning of Double.Epsilon

                          cody <no_spam_deutro nium@gmx.net> wrote:[color=blue][color=green]
                          > > The member variable is strictly 32 bits, but the local variable can be
                          > > enregistered - so it ends up being more accurate than the member
                          > > variable, and the comparison fails (on my box).[/color]
                          >
                          > Now I remember it was you with the example. But I still do not get it.
                          > The explanation given by Niki seemed logical.
                          > So if we never know which variable is put in which register so we can never
                          > rely on that a comparison of two floating point variables will succeed?
                          > So it stands as it is: Equality testing with floating point variables is
                          > never a good idea because the result is undefined.[/color]

                          If the result is from a calculation, that's right. I believe that if
                          it's from a constant, or if it's from a calculation which has an answer
                          which can be exactly represented in the chosen data size, it's fine.

                          I suspect it's very, very rarely a good idea to use == for comparisons
                          with non-constants in the first place though.

                          --
                          Jon Skeet - <skeet@pobox.co m>
                          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                          If replying to the group, please do not mail me too

                          Comment

                          • Niki Estner

                            #28
                            Re: Meaning of Double.Epsilon

                            "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in
                            news:MPG.1baa8d 3996904a3998b3a b@msnews.micros oft.com...[color=blue]
                            > cody <no_spam_deutro nium@gmx.net> wrote:[color=green][color=darkred]
                            >> > The member variable is strictly 32 bits, but the local variable can be
                            >> > enregistered - so it ends up being more accurate than the member
                            >> > variable, and the comparison fails (on my box).[/color]
                            >>
                            >> Now I remember it was you with the example. But I still do not get it.
                            >> The explanation given by Niki seemed logical.
                            >> So if we never know which variable is put in which register so we can
                            >> never
                            >> rely on that a comparison of two floating point variables will succeed?
                            >> So it stands as it is: Equality testing with floating point variables is
                            >> never a good idea because the result is undefined.[/color]
                            >
                            > If the result is from a calculation, that's right. I believe that if
                            > it's from a constant, or if it's from a calculation which has an answer
                            > which can be exactly represented in the chosen data size, it's fine.[/color]

                            Constant are ok, but calculation results usually aren't safe:
                            Console.WriteLi ne(Math.Sqrt(2) *Math.Sqrt(2) == 2);
                            prints out false on my machine.
                            [color=blue]
                            > I suspect it's very, very rarely a good idea to use == for comparisons
                            > with non-constants in the first place though.[/color]

                            I'd definitely agree to that.

                            Niki


                            Comment

                            • Jon Skeet [C# MVP]

                              #29
                              Re: Meaning of Double.Epsilon

                              Niki Estner <niki.estner@cu be.net> wrote:[color=blue][color=green]
                              > > If the result is from a calculation, that's right. I believe that if
                              > > it's from a constant, or if it's from a calculation which has an answer
                              > > which can be exactly represented in the chosen data size, it's fine.[/color]
                              >
                              > Constant are ok, but calculation results usually aren't safe:
                              > Console.WriteLi ne(Math.Sqrt(2) *Math.Sqrt(2) == 2);
                              > prints out false on my machine.[/color]

                              Well, I'd say that's a slightly different problem again - that's just
                              the general inaccuracies of floating point arithmetic, rather than
                              being due to conversions from an 80-bit value to a 64-bit value. I
                              think it's unreasonable to expect the above to print True necessarily,
                              but take:

                              double b = Math.Sqrt(2);
                              Console.WriteLi ne (b==Math.Sqrt(2 ));

                              I think it's reasonable to expect that to print True, but it may not.
                              (I'm not saying it's a bad thing for it not to, other than being
                              counter-intuitive. I understand the reasons for why things work the way
                              they do.)

                              --
                              Jon Skeet - <skeet@pobox.co m>
                              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                              If replying to the group, please do not mail me too

                              Comment

                              • cody

                                #30
                                Re: Meaning of Double.Epsilon

                                > >> > The member variable is strictly 32 bits, but the local variable can
                                be[color=blue][color=green][color=darkred]
                                > >> > enregistered - so it ends up being more accurate than the member
                                > >> > variable, and the comparison fails (on my box).
                                > >>
                                > >> Now I remember it was you with the example. But I still do not get it.
                                > >> The explanation given by Niki seemed logical.
                                > >> So if we never know which variable is put in which register so we can
                                > >> never
                                > >> rely on that a comparison of two floating point variables will[/color][/color][/color]
                                succeed?[color=blue][color=green][color=darkred]
                                > >> So it stands as it is: Equality testing with floating point variables[/color][/color][/color]
                                is[color=blue][color=green][color=darkred]
                                > >> never a good idea because the result is undefined.[/color]
                                > >
                                > > If the result is from a calculation, that's right. I believe that if
                                > > it's from a constant, or if it's from a calculation which has an answer
                                > > which can be exactly represented in the chosen data size, it's fine.[/color][/color]

                                But in Jons example the calculation can be left can certainly out without
                                altering the meaning the program because it compares the results of two same
                                calculations using constants only.
                                [color=blue]
                                > Constant are ok, but calculation results usually aren't safe:
                                > Console.WriteLi ne(Math.Sqrt(2) *Math.Sqrt(2) == 2);
                                > prints out false on my machine.[/color]

                                I wouldn't have expected any other result than a random value from 'true'
                                and 'false' :)

                                I always have been thinking of floating point values as "fuzzy things" where
                                the exact representation of the result of a calculation is not foreseeable.
                                Maybe there are IEEE standards but who knows where some machines calculates
                                floating point in their own way? I do not care as long as the result comes
                                very close to the "real" exact result.
                                [color=blue][color=green]
                                > > I suspect it's very, very rarely a good idea to use == for comparisons
                                > > with non-constants in the first place though.[/color]
                                >
                                > I'd definitely agree to that.[/color]

                                Who wouldn't agree with that (except the microsoft guy who decided that
                                operator== for fp do not need a compiler warning).

                                --
                                cody

                                [Freeware, Games and Humor]
                                www.deutronium.de.vu || www.deutronium.tk


                                Comment

                                Working...