float/double Math.Round in C#












6















float ff = (float)31.15;

double dd = 31.15;

var frst = Math.Round(ff, 1, MidpointRounding.AwayFromZero);

var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


frst: 31.1



drst: 31.2



Can someone explain why?










share|improve this question




















  • 2





    Because (float)31.15 is not equal to (double)31.15. Floating-point-arithmetic allmost allways yields to rounding-erros. In paticular rounding a double works different from rounding a float.

    – HimBromBeere
    57 mins ago













  • Don't use float. Always decimal or double.

    – i486
    52 mins ago






  • 1





    Rounding errors are unavoidable with floating point values. They are as unavoidable as death and taxes : youtube.com/watch?v=PZRI1IfStY0

    – Christopher
    51 mins ago






  • 1





    Possible duplicate of Difference between decimal, float and double in .NET?

    – Jan S.
    50 mins ago






  • 1





    @i486 Well, not always, there is a reason why float exists.

    – SeM
    49 mins ago
















6















float ff = (float)31.15;

double dd = 31.15;

var frst = Math.Round(ff, 1, MidpointRounding.AwayFromZero);

var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


frst: 31.1



drst: 31.2



Can someone explain why?










share|improve this question




















  • 2





    Because (float)31.15 is not equal to (double)31.15. Floating-point-arithmetic allmost allways yields to rounding-erros. In paticular rounding a double works different from rounding a float.

    – HimBromBeere
    57 mins ago













  • Don't use float. Always decimal or double.

    – i486
    52 mins ago






  • 1





    Rounding errors are unavoidable with floating point values. They are as unavoidable as death and taxes : youtube.com/watch?v=PZRI1IfStY0

    – Christopher
    51 mins ago






  • 1





    Possible duplicate of Difference between decimal, float and double in .NET?

    – Jan S.
    50 mins ago






  • 1





    @i486 Well, not always, there is a reason why float exists.

    – SeM
    49 mins ago














6












6








6


2






float ff = (float)31.15;

double dd = 31.15;

var frst = Math.Round(ff, 1, MidpointRounding.AwayFromZero);

var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


frst: 31.1



drst: 31.2



Can someone explain why?










share|improve this question
















float ff = (float)31.15;

double dd = 31.15;

var frst = Math.Round(ff, 1, MidpointRounding.AwayFromZero);

var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


frst: 31.1



drst: 31.2



Can someone explain why?







c# rounding






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 32 mins ago









Dmitry Bychenko

107k1092133




107k1092133










asked 1 hour ago









YaoqingYaoqing

601




601








  • 2





    Because (float)31.15 is not equal to (double)31.15. Floating-point-arithmetic allmost allways yields to rounding-erros. In paticular rounding a double works different from rounding a float.

    – HimBromBeere
    57 mins ago













  • Don't use float. Always decimal or double.

    – i486
    52 mins ago






  • 1





    Rounding errors are unavoidable with floating point values. They are as unavoidable as death and taxes : youtube.com/watch?v=PZRI1IfStY0

    – Christopher
    51 mins ago






  • 1





    Possible duplicate of Difference between decimal, float and double in .NET?

    – Jan S.
    50 mins ago






  • 1





    @i486 Well, not always, there is a reason why float exists.

    – SeM
    49 mins ago














  • 2





    Because (float)31.15 is not equal to (double)31.15. Floating-point-arithmetic allmost allways yields to rounding-erros. In paticular rounding a double works different from rounding a float.

    – HimBromBeere
    57 mins ago













  • Don't use float. Always decimal or double.

    – i486
    52 mins ago






  • 1





    Rounding errors are unavoidable with floating point values. They are as unavoidable as death and taxes : youtube.com/watch?v=PZRI1IfStY0

    – Christopher
    51 mins ago






  • 1





    Possible duplicate of Difference between decimal, float and double in .NET?

    – Jan S.
    50 mins ago






  • 1





    @i486 Well, not always, there is a reason why float exists.

    – SeM
    49 mins ago








2




2





Because (float)31.15 is not equal to (double)31.15. Floating-point-arithmetic allmost allways yields to rounding-erros. In paticular rounding a double works different from rounding a float.

– HimBromBeere
57 mins ago







Because (float)31.15 is not equal to (double)31.15. Floating-point-arithmetic allmost allways yields to rounding-erros. In paticular rounding a double works different from rounding a float.

– HimBromBeere
57 mins ago















Don't use float. Always decimal or double.

– i486
52 mins ago





Don't use float. Always decimal or double.

– i486
52 mins ago




1




1





Rounding errors are unavoidable with floating point values. They are as unavoidable as death and taxes : youtube.com/watch?v=PZRI1IfStY0

– Christopher
51 mins ago





Rounding errors are unavoidable with floating point values. They are as unavoidable as death and taxes : youtube.com/watch?v=PZRI1IfStY0

– Christopher
51 mins ago




1




1





Possible duplicate of Difference between decimal, float and double in .NET?

– Jan S.
50 mins ago





Possible duplicate of Difference between decimal, float and double in .NET?

– Jan S.
50 mins ago




1




1





@i486 Well, not always, there is a reason why float exists.

– SeM
49 mins ago





@i486 Well, not always, there is a reason why float exists.

– SeM
49 mins ago












3 Answers
3






active

oldest

votes


















11














Well, Math.Round wants double, not float, that's why



Math.Round(ff, 1, MidpointRounding.AwayFromZero);


equals to



Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);


and if we inspect (double)ff value



Console.Write(((double)ff).ToString("R"));


we'll see round up errors in action



31.149999618530273


Finally, Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1 as expected






share|improve this answer
























  • I'm curious why (double)ff is exactly 31.14999961853027 and not 31.150000000000000

    – Gonzalo Lorieto
    49 mins ago






  • 3





    @Gonzalo Lorieto: double is binary and 0.15 == 15 / 100 = 3 / 20 is a periodic fraction in binary representation.

    – Dmitry Bychenko
    48 mins ago






  • 1





    @GonzaloLorieto stackoverflow.com/questions/618535/…

    – Camilo Terevinto
    47 mins ago






  • 1





    @GonzaloLorieto You can read it here -> Floating-point arithmetic

    – SeM
    47 mins ago



















3














In floating point, all numbers are represented internally as fractions where the denominator is a power of 2.



(This is a similar way to how decimals are actually fractions with power-of-10 denominators. So 31.15 is just a way of writing the fraction 3115/100)



In floating point, 31.15 must be represented internally as a binary number. The closest binary fraction is: 1111.1001001100110011001100110011001100110011001100110011001100...repeating



The 1100 recurs (repeats forever), and so the number will be truncated depending on whether it is stored in a double or a float. In a float it is truncated to 24 digits, and in a double to 53.



Exact:  1111.100100110011001100110011001100110011001100110011001100110011001100...forever
Float: 1111.10010011001100110011
Double: 1111.1001001100110011001100110011001100110011001100110


Therefore you can see that the double that this number converts to, is actually slightly larger than the float it converts to. So it is clear that it won't necessarily round to the same number, since it is not the same number to begin with.






share|improve this answer

































    0














    It is already explained why we do have that rounding problem but it is worth mentioning that with this small trick you can get away of it:



    float ff = (float)31.15;

    double dd = 31.15;

    var frst = Math.Round(
    double.Parse(ff.ToString(CultureInfo.InvariantCulture)),
    1,
    MidpointRounding.AwayFromZero);

    var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


    Then the result should be the same:



    3.2
    3.2


    so while (double)ff introduce rounding problem, double.Parse(ff.ToString()) doesn't, kind a logical but weird in any case.






    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54235885%2ffloat-double-math-round-in-c-sharp%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      11














      Well, Math.Round wants double, not float, that's why



      Math.Round(ff, 1, MidpointRounding.AwayFromZero);


      equals to



      Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);


      and if we inspect (double)ff value



      Console.Write(((double)ff).ToString("R"));


      we'll see round up errors in action



      31.149999618530273


      Finally, Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1 as expected






      share|improve this answer
























      • I'm curious why (double)ff is exactly 31.14999961853027 and not 31.150000000000000

        – Gonzalo Lorieto
        49 mins ago






      • 3





        @Gonzalo Lorieto: double is binary and 0.15 == 15 / 100 = 3 / 20 is a periodic fraction in binary representation.

        – Dmitry Bychenko
        48 mins ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        47 mins ago






      • 1





        @GonzaloLorieto You can read it here -> Floating-point arithmetic

        – SeM
        47 mins ago
















      11














      Well, Math.Round wants double, not float, that's why



      Math.Round(ff, 1, MidpointRounding.AwayFromZero);


      equals to



      Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);


      and if we inspect (double)ff value



      Console.Write(((double)ff).ToString("R"));


      we'll see round up errors in action



      31.149999618530273


      Finally, Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1 as expected






      share|improve this answer
























      • I'm curious why (double)ff is exactly 31.14999961853027 and not 31.150000000000000

        – Gonzalo Lorieto
        49 mins ago






      • 3





        @Gonzalo Lorieto: double is binary and 0.15 == 15 / 100 = 3 / 20 is a periodic fraction in binary representation.

        – Dmitry Bychenko
        48 mins ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        47 mins ago






      • 1





        @GonzaloLorieto You can read it here -> Floating-point arithmetic

        – SeM
        47 mins ago














      11












      11








      11







      Well, Math.Round wants double, not float, that's why



      Math.Round(ff, 1, MidpointRounding.AwayFromZero);


      equals to



      Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);


      and if we inspect (double)ff value



      Console.Write(((double)ff).ToString("R"));


      we'll see round up errors in action



      31.149999618530273


      Finally, Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1 as expected






      share|improve this answer













      Well, Math.Round wants double, not float, that's why



      Math.Round(ff, 1, MidpointRounding.AwayFromZero);


      equals to



      Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);


      and if we inspect (double)ff value



      Console.Write(((double)ff).ToString("R"));


      we'll see round up errors in action



      31.149999618530273


      Finally, Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1 as expected







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered 54 mins ago









      Dmitry BychenkoDmitry Bychenko

      107k1092133




      107k1092133













      • I'm curious why (double)ff is exactly 31.14999961853027 and not 31.150000000000000

        – Gonzalo Lorieto
        49 mins ago






      • 3





        @Gonzalo Lorieto: double is binary and 0.15 == 15 / 100 = 3 / 20 is a periodic fraction in binary representation.

        – Dmitry Bychenko
        48 mins ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        47 mins ago






      • 1





        @GonzaloLorieto You can read it here -> Floating-point arithmetic

        – SeM
        47 mins ago



















      • I'm curious why (double)ff is exactly 31.14999961853027 and not 31.150000000000000

        – Gonzalo Lorieto
        49 mins ago






      • 3





        @Gonzalo Lorieto: double is binary and 0.15 == 15 / 100 = 3 / 20 is a periodic fraction in binary representation.

        – Dmitry Bychenko
        48 mins ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        47 mins ago






      • 1





        @GonzaloLorieto You can read it here -> Floating-point arithmetic

        – SeM
        47 mins ago

















      I'm curious why (double)ff is exactly 31.14999961853027 and not 31.150000000000000

      – Gonzalo Lorieto
      49 mins ago





      I'm curious why (double)ff is exactly 31.14999961853027 and not 31.150000000000000

      – Gonzalo Lorieto
      49 mins ago




      3




      3





      @Gonzalo Lorieto: double is binary and 0.15 == 15 / 100 = 3 / 20 is a periodic fraction in binary representation.

      – Dmitry Bychenko
      48 mins ago





      @Gonzalo Lorieto: double is binary and 0.15 == 15 / 100 = 3 / 20 is a periodic fraction in binary representation.

      – Dmitry Bychenko
      48 mins ago




      1




      1





      @GonzaloLorieto stackoverflow.com/questions/618535/…

      – Camilo Terevinto
      47 mins ago





      @GonzaloLorieto stackoverflow.com/questions/618535/…

      – Camilo Terevinto
      47 mins ago




      1




      1





      @GonzaloLorieto You can read it here -> Floating-point arithmetic

      – SeM
      47 mins ago





      @GonzaloLorieto You can read it here -> Floating-point arithmetic

      – SeM
      47 mins ago













      3














      In floating point, all numbers are represented internally as fractions where the denominator is a power of 2.



      (This is a similar way to how decimals are actually fractions with power-of-10 denominators. So 31.15 is just a way of writing the fraction 3115/100)



      In floating point, 31.15 must be represented internally as a binary number. The closest binary fraction is: 1111.1001001100110011001100110011001100110011001100110011001100...repeating



      The 1100 recurs (repeats forever), and so the number will be truncated depending on whether it is stored in a double or a float. In a float it is truncated to 24 digits, and in a double to 53.



      Exact:  1111.100100110011001100110011001100110011001100110011001100110011001100...forever
      Float: 1111.10010011001100110011
      Double: 1111.1001001100110011001100110011001100110011001100110


      Therefore you can see that the double that this number converts to, is actually slightly larger than the float it converts to. So it is clear that it won't necessarily round to the same number, since it is not the same number to begin with.






      share|improve this answer






























        3














        In floating point, all numbers are represented internally as fractions where the denominator is a power of 2.



        (This is a similar way to how decimals are actually fractions with power-of-10 denominators. So 31.15 is just a way of writing the fraction 3115/100)



        In floating point, 31.15 must be represented internally as a binary number. The closest binary fraction is: 1111.1001001100110011001100110011001100110011001100110011001100...repeating



        The 1100 recurs (repeats forever), and so the number will be truncated depending on whether it is stored in a double or a float. In a float it is truncated to 24 digits, and in a double to 53.



        Exact:  1111.100100110011001100110011001100110011001100110011001100110011001100...forever
        Float: 1111.10010011001100110011
        Double: 1111.1001001100110011001100110011001100110011001100110


        Therefore you can see that the double that this number converts to, is actually slightly larger than the float it converts to. So it is clear that it won't necessarily round to the same number, since it is not the same number to begin with.






        share|improve this answer




























          3












          3








          3







          In floating point, all numbers are represented internally as fractions where the denominator is a power of 2.



          (This is a similar way to how decimals are actually fractions with power-of-10 denominators. So 31.15 is just a way of writing the fraction 3115/100)



          In floating point, 31.15 must be represented internally as a binary number. The closest binary fraction is: 1111.1001001100110011001100110011001100110011001100110011001100...repeating



          The 1100 recurs (repeats forever), and so the number will be truncated depending on whether it is stored in a double or a float. In a float it is truncated to 24 digits, and in a double to 53.



          Exact:  1111.100100110011001100110011001100110011001100110011001100110011001100...forever
          Float: 1111.10010011001100110011
          Double: 1111.1001001100110011001100110011001100110011001100110


          Therefore you can see that the double that this number converts to, is actually slightly larger than the float it converts to. So it is clear that it won't necessarily round to the same number, since it is not the same number to begin with.






          share|improve this answer















          In floating point, all numbers are represented internally as fractions where the denominator is a power of 2.



          (This is a similar way to how decimals are actually fractions with power-of-10 denominators. So 31.15 is just a way of writing the fraction 3115/100)



          In floating point, 31.15 must be represented internally as a binary number. The closest binary fraction is: 1111.1001001100110011001100110011001100110011001100110011001100...repeating



          The 1100 recurs (repeats forever), and so the number will be truncated depending on whether it is stored in a double or a float. In a float it is truncated to 24 digits, and in a double to 53.



          Exact:  1111.100100110011001100110011001100110011001100110011001100110011001100...forever
          Float: 1111.10010011001100110011
          Double: 1111.1001001100110011001100110011001100110011001100110


          Therefore you can see that the double that this number converts to, is actually slightly larger than the float it converts to. So it is clear that it won't necessarily round to the same number, since it is not the same number to begin with.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 20 mins ago

























          answered 42 mins ago









          BenBen

          28.7k55487




          28.7k55487























              0














              It is already explained why we do have that rounding problem but it is worth mentioning that with this small trick you can get away of it:



              float ff = (float)31.15;

              double dd = 31.15;

              var frst = Math.Round(
              double.Parse(ff.ToString(CultureInfo.InvariantCulture)),
              1,
              MidpointRounding.AwayFromZero);

              var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


              Then the result should be the same:



              3.2
              3.2


              so while (double)ff introduce rounding problem, double.Parse(ff.ToString()) doesn't, kind a logical but weird in any case.






              share|improve this answer






























                0














                It is already explained why we do have that rounding problem but it is worth mentioning that with this small trick you can get away of it:



                float ff = (float)31.15;

                double dd = 31.15;

                var frst = Math.Round(
                double.Parse(ff.ToString(CultureInfo.InvariantCulture)),
                1,
                MidpointRounding.AwayFromZero);

                var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


                Then the result should be the same:



                3.2
                3.2


                so while (double)ff introduce rounding problem, double.Parse(ff.ToString()) doesn't, kind a logical but weird in any case.






                share|improve this answer




























                  0












                  0








                  0







                  It is already explained why we do have that rounding problem but it is worth mentioning that with this small trick you can get away of it:



                  float ff = (float)31.15;

                  double dd = 31.15;

                  var frst = Math.Round(
                  double.Parse(ff.ToString(CultureInfo.InvariantCulture)),
                  1,
                  MidpointRounding.AwayFromZero);

                  var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


                  Then the result should be the same:



                  3.2
                  3.2


                  so while (double)ff introduce rounding problem, double.Parse(ff.ToString()) doesn't, kind a logical but weird in any case.






                  share|improve this answer















                  It is already explained why we do have that rounding problem but it is worth mentioning that with this small trick you can get away of it:



                  float ff = (float)31.15;

                  double dd = 31.15;

                  var frst = Math.Round(
                  double.Parse(ff.ToString(CultureInfo.InvariantCulture)),
                  1,
                  MidpointRounding.AwayFromZero);

                  var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);


                  Then the result should be the same:



                  3.2
                  3.2


                  so while (double)ff introduce rounding problem, double.Parse(ff.ToString()) doesn't, kind a logical but weird in any case.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 22 mins ago

























                  answered 38 mins ago









                  JohnnyJohnny

                  1,704615




                  1,704615






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54235885%2ffloat-double-math-round-in-c-sharp%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Polycentropodidae

                      Magento 2 Error message: Invalid state change requested

                      Paulmy