Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. doubles a == b or not ?

doubles a == b or not ?

Scheduled Pinned Locked Moved Clever Code
csharphelpquestion
33 Posts 14 Posters 18 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P peterchen

    I am not sure how IEEE floats work, but inf-x=inf works only for finite x. inf-inf should in any case end up NaN, and no matter how this expression is evaluated, you will end up with that subexpression at one point, and once any operand is NaN, it should stick.


    I googled, here's what I came upon: scroll down to "special operations": Clickety[^]

    Burning Chrome ^ | Linkify!| FoldWithUs! | sighist

    S Offline
    S Offline
    supercat9
    wrote on last edited by
    #18

    I should have said that the indicated mathematical expression could yield four different results depending upon the order in which the terms were grouped. If the expression is coded in a particular form, the language's standard rules of associativity will dictate how the terms are grouped, but if it is computed using something like a sum() method on a database field, such behavior would not be guaranteed. While it wouldn't seem particularly likely that an implementation would separately sum together the two positive terms and the two negative terms before adding the two sums, such an approach would generally yield better precision than adding everything in sequence.

    P 1 Reply Last reply
    0
    • S supercat9

      I should have said that the indicated mathematical expression could yield four different results depending upon the order in which the terms were grouped. If the expression is coded in a particular form, the language's standard rules of associativity will dictate how the terms are grouped, but if it is computed using something like a sum() method on a database field, such behavior would not be guaranteed. While it wouldn't seem particularly likely that an implementation would separately sum together the two positive terms and the two negative terms before adding the two sums, such an approach would generally yield better precision than adding everything in sequence.

      P Offline
      P Offline
      peterchen
      wrote on last edited by
      #19

      My point was that grouping doesn't matter if you define the arithmetics for special values correctly (Which the IEEE standard apparently does)

      Burning Chrome ^ | Linkify!| FoldWithUs! | sighist

      S 1 Reply Last reply
      0
      • P peterchen

        My point was that grouping doesn't matter if you define the arithmetics for special values correctly (Which the IEEE standard apparently does)

        Burning Chrome ^ | Linkify!| FoldWithUs! | sighist

        S Offline
        S Offline
        supercat9
        wrote on last edited by
        #20

        Grouping very much does matter. Adding together the four items: +x, +x, -x, -x (where x is the the largest number short of infinity) If they are grouped as (+x + +x) + (-x + -x) the result will be (+inf) + (-inf), or NaN. If they are grouped as ((+x + +x) + -x) + -x the result will be (+inf + -x) + -x, or +inf + -x, or +inf. If they are grouped as +x + (+x + (-x + -x)) the result will be +x + (+x + -inf), or +x + -inf, or -inf. If they are grouped as (+x + (+x + -x)) + -x, the result will be (+x + 0) + -x, or +x + -x, or zero. With which of those statements do you disagree.

        P C 2 Replies Last reply
        0
        • S supercat9

          Grouping very much does matter. Adding together the four items: +x, +x, -x, -x (where x is the the largest number short of infinity) If they are grouped as (+x + +x) + (-x + -x) the result will be (+inf) + (-inf), or NaN. If they are grouped as ((+x + +x) + -x) + -x the result will be (+inf + -x) + -x, or +inf + -x, or +inf. If they are grouped as +x + (+x + (-x + -x)) the result will be +x + (+x + -inf), or +x + -inf, or -inf. If they are grouped as (+x + (+x + -x)) + -x, the result will be (+x + 0) + -x, or +x + -x, or zero. With which of those statements do you disagree.

          P Offline
          P Offline
          peterchen
          wrote on last edited by
          #21

          supercat9 wrote:

          largest number short of infinity

          ohhh... I missed that all the time :sigh:

          Burning Chrome ^ | Linkify!| FoldWithUs! | sighist

          D 1 Reply Last reply
          0
          • P peterchen

            supercat9 wrote:

            largest number short of infinity

            ohhh... I missed that all the time :sigh:

            Burning Chrome ^ | Linkify!| FoldWithUs! | sighist

            D Offline
            D Offline
            Dan Neely
            wrote on last edited by
            #22

            Don't feel too bad, I almost did the same thing.

            Today's lesson is brought to you by the word "niggardly". Remember kids, don't attribute to racism what can be explained by Scandinavian language roots. -- Robert Royall

            1 Reply Last reply
            0
            • A akidan

              Correct, nice job. :) Basically, the IEEE definition of equality for floating points requires NaN != NaN (see here)... but the .NET definition of equality requires that a.Equals(a). (Otherwise, you'd never be able to get anything back out of a Dictionary if the key had a NaN in it). So floats and doubles have a special clause in their Equals operator that checks for NaN for this reason.

              J Offline
              J Offline
              jhwurmbach
              wrote on last edited by
              #23

              akidan wrote:

              the .NET definition of equality requires that a.Equals(a). (Otherwise, you'd never be able to get anything back out of a Dictionary if the key had a NaN in it

              And that would be a problem? Whoever sticks a NaN into a dictionary deserves to not get the values back! NaN is defined as "This is a marker for overflow somewhere. It is not comparable with anything."

              Let's think the unthinkable, let's do the undoable, let's prepare to grapple with the ineffable itself, and see if we may not eff it after all.
              Douglas Adams, "Dirk Gently's Holistic Detective Agency"

              L A 2 Replies Last reply
              0
              • J jhwurmbach

                akidan wrote:

                the .NET definition of equality requires that a.Equals(a). (Otherwise, you'd never be able to get anything back out of a Dictionary if the key had a NaN in it

                And that would be a problem? Whoever sticks a NaN into a dictionary deserves to not get the values back! NaN is defined as "This is a marker for overflow somewhere. It is not comparable with anything."

                Let's think the unthinkable, let's do the undoable, let's prepare to grapple with the ineffable itself, and see if we may not eff it after all.
                Douglas Adams, "Dirk Gently's Holistic Detective Agency"

                L Offline
                L Offline
                Luc Pattyn
                wrote on last edited by
                #24

                Now if you keep adding all kinds of NaNs to a dictionary, it will overflow too. :)

                Luc Pattyn [Forum Guidelines] [My Articles]


                - before you ask a question here, search CodeProject, then Google - the quality and detail of your question reflects on the effectiveness of the help you are likely to get - use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets


                1 Reply Last reply
                0
                • J jhwurmbach

                  akidan wrote:

                  the .NET definition of equality requires that a.Equals(a). (Otherwise, you'd never be able to get anything back out of a Dictionary if the key had a NaN in it

                  And that would be a problem? Whoever sticks a NaN into a dictionary deserves to not get the values back! NaN is defined as "This is a marker for overflow somewhere. It is not comparable with anything."

                  Let's think the unthinkable, let's do the undoable, let's prepare to grapple with the ineffable itself, and see if we may not eff it after all.
                  Douglas Adams, "Dirk Gently's Holistic Detective Agency"

                  A Offline
                  A Offline
                  akidan
                  wrote on last edited by
                  #25

                  Part of having a unified type system means that there is no difference between float64-the-primitive and System.Double-the-object - they must be treated as one and the same. However, now you have a contradiction. The definition of equality for floating point numbers is fundamentally incompatible with the contract for equality of objects in .NET. Floating point requires that NaN must not equal NaN. System.Object requires that a.Equals(a) returns true. If you make a special exception for the a.Equals(a) rule for doubles and floats, you have now broken the contract of equality for objects and thus broken polymorphism. One can no longer write code under the assumption that a.Equals(a) always holds true.

                  J 1 Reply Last reply
                  0
                  • A akidan

                    Part of having a unified type system means that there is no difference between float64-the-primitive and System.Double-the-object - they must be treated as one and the same. However, now you have a contradiction. The definition of equality for floating point numbers is fundamentally incompatible with the contract for equality of objects in .NET. Floating point requires that NaN must not equal NaN. System.Object requires that a.Equals(a) returns true. If you make a special exception for the a.Equals(a) rule for doubles and floats, you have now broken the contract of equality for objects and thus broken polymorphism. One can no longer write code under the assumption that a.Equals(a) always holds true.

                    J Offline
                    J Offline
                    jhwurmbach
                    wrote on last edited by
                    #26

                    akidan wrote:

                    If you make a special exception for the a.Equals(a) rule for doubles and floats, you have now broken the contract of equality for objects

                    Sure. And this way, you have broken the contract of IEEE math. And guess what's older... But I admit - you are to die one death, and .NET choose to violate the math rules.

                    Let's think the unthinkable, let's do the undoable, let's prepare to grapple with the ineffable itself, and see if we may not eff it after all.
                    Douglas Adams, "Dirk Gently's Holistic Detective Agency"

                    A 1 Reply Last reply
                    0
                    • J jhwurmbach

                      akidan wrote:

                      If you make a special exception for the a.Equals(a) rule for doubles and floats, you have now broken the contract of equality for objects

                      Sure. And this way, you have broken the contract of IEEE math. And guess what's older... But I admit - you are to die one death, and .NET choose to violate the math rules.

                      Let's think the unthinkable, let's do the undoable, let's prepare to grapple with the ineffable itself, and see if we may not eff it after all.
                      Douglas Adams, "Dirk Gently's Holistic Detective Agency"

                      A Offline
                      A Offline
                      akidan
                      wrote on last edited by
                      #27

                      No, the contract is not broken for IEEE math. ceq on float32/float64 obeys the rules. (double.NaN != double.NaN and float.NaN != float.NaN)

                      1 Reply Last reply
                      0
                      • R realJSOP

                        A wise developer would never compare a double or float for equality without washing the data first.

                        "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
                        -----
                        "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

                        C Offline
                        C Offline
                        CPallini
                        wrote on last edited by
                        #28

                        A wise developer uses only ints. :)

                        If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                        This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
                        [My articles]

                        1 Reply Last reply
                        0
                        • R Rudi Breedenraedt

                          Well, actually this is not really a bug, but a very strange behavior of the .NET double type. I'll put it as a riddle and let you find it out ! Ok, if no one found it, I'll post the answer, over a couple of days, time to let you search... ;) Take the following method:

                          public static string LittleTest(double a, double b)
                          {
                          double x = 5.0;

                          if (a != b)
                          	return "Try other values for a and b...";
                          
                          double xa = x / a;
                          double xb = x / b;
                          
                          if (xa == xb)
                          	return "Not yet right...";
                          else
                          	return "You've got it !!!";
                          

                          }

                          For which values a and b will the method return "You've got it !!!" ???

                          R Offline
                          R Offline
                          Ri Qen Sin
                          wrote on last edited by
                          #29

                          I'm tempted to use the Decimal type whenever I can to make results more predictable.

                          So the creationist says: Everything must have a designer. God designed everything. I say: Why is God the only exception? Why not make the "designs" (like man) exceptions and make God a creation of man?

                          1 Reply Last reply
                          0
                          • L Lost User

                            Zero and negative zero

                            M Offline
                            M Offline
                            Megidolaon
                            wrote on last edited by
                            #30

                            What is negative zero?:confused:

                            L 1 Reply Last reply
                            0
                            • M Megidolaon

                              What is negative zero?:confused:

                              L Offline
                              L Offline
                              Lost User
                              wrote on last edited by
                              #31

                              -0 It's zero with the sign flipped As a double the binary representation is 0x8000000000000000, as a normal float it is 0x80000000 It's defined to compare equal to itself, but the sign influences the result of many other operations on it.

                              1 Reply Last reply
                              0
                              • S supercat9

                                Grouping very much does matter. Adding together the four items: +x, +x, -x, -x (where x is the the largest number short of infinity) If they are grouped as (+x + +x) + (-x + -x) the result will be (+inf) + (-inf), or NaN. If they are grouped as ((+x + +x) + -x) + -x the result will be (+inf + -x) + -x, or +inf + -x, or +inf. If they are grouped as +x + (+x + (-x + -x)) the result will be +x + (+x + -inf), or +x + -inf, or -inf. If they are grouped as (+x + (+x + -x)) + -x, the result will be (+x + 0) + -x, or +x + -x, or zero. With which of those statements do you disagree.

                                C Offline
                                C Offline
                                Christoph Menge
                                wrote on last edited by
                                #32

                                Well, I have a question there. Maybe I am getting something wrong. I agree these statements hold true if you force the result into a temporary variable, e.g.

                                double x1 = x + x;
                                double x2 = x - x;
                                then x1 + x2 = Infinity + 0 = Infinity

                                (or float, alternatively). However, as long as the statement is not forced into a double, the value is computed with 80bit precision, thereby correctly evaluating to 0.0 in all cases given?! From the little I remember from assembly, you will push values onto the (80bit) floating-point stack using fld, then perform floating point operations such as fadd, fsub, fmul (which expects its arguments at positions 0, 1 of the fp-stack and moves its results to st0), and pop the result off the stack using fstp or fistp for integer-targets. This raises the interesting question of debug vs. release: If the compiler optimized floating-point code, it would allow for more precision by holding temporary results in the fp-stack. While this would increase precision, it'd also cause inconsistent behaviour. I haven't encountered the latter so it probably doesn't, but it might be worth checking. EDIT: I just found this interesting post on the net, addressing exactly these issues: http://blogs.msdn.com/davidnotario/archive/2005/08/08/449092.aspx[^]

                                "Obstacles are those frightening things you see when you take your Eyes off your aim" - Henry Ford
                                Articles  Blog

                                S 1 Reply Last reply
                                0
                                • C Christoph Menge

                                  Well, I have a question there. Maybe I am getting something wrong. I agree these statements hold true if you force the result into a temporary variable, e.g.

                                  double x1 = x + x;
                                  double x2 = x - x;
                                  then x1 + x2 = Infinity + 0 = Infinity

                                  (or float, alternatively). However, as long as the statement is not forced into a double, the value is computed with 80bit precision, thereby correctly evaluating to 0.0 in all cases given?! From the little I remember from assembly, you will push values onto the (80bit) floating-point stack using fld, then perform floating point operations such as fadd, fsub, fmul (which expects its arguments at positions 0, 1 of the fp-stack and moves its results to st0), and pop the result off the stack using fstp or fistp for integer-targets. This raises the interesting question of debug vs. release: If the compiler optimized floating-point code, it would allow for more precision by holding temporary results in the fp-stack. While this would increase precision, it'd also cause inconsistent behaviour. I haven't encountered the latter so it probably doesn't, but it might be worth checking. EDIT: I just found this interesting post on the net, addressing exactly these issues: http://blogs.msdn.com/davidnotario/archive/2005/08/08/449092.aspx[^]

                                  "Obstacles are those frightening things you see when you take your Eyes off your aim" - Henry Ford
                                  Articles  Blog

                                  S Offline
                                  S Offline
                                  supercat9
                                  wrote on last edited by
                                  #33

                                  However, as long as the statement is not forced into a double, the value is computed with 80bit precision, thereby correctly evaluating to 0.0 in all cases given?! Interesting point; I'd forgotten that the 80-bit type has a larger exponent range as well as a larger mantissa, and thus that the operation that would overflow a type 'double' won't overflow the internal-precision type. That does raise a question, though, of why there is no facility to store the extended-precision type anywhere? I understand that given word-alignment issues it may not be practical to store a packed 10-byte type, but I would think it would have been useful to have a 16-byte floating-point type which is guaranteed to hold any floating-point number to full internal representation (on machines with 80-bit floats, six bytes would be unused). Programmers would be encouraged to use type 'double' for long-term data storage, but would be able to use the extended precision for calculations where it matters.

                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • World
                                  • Users
                                  • Groups