float/double Math.Round in C#












12















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
    2 hours ago








  • 1





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

    – Christopher
    1 hour ago






  • 1





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

    – Jan S.
    1 hour ago






  • 3





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

    – SeM
    1 hour ago






  • 2





    @i486 Again, that doesn't mean, that you should never use float.

    – SeM
    56 mins ago
















12















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
    2 hours ago








  • 1





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

    – Christopher
    1 hour ago






  • 1





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

    – Jan S.
    1 hour ago






  • 3





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

    – SeM
    1 hour ago






  • 2





    @i486 Again, that doesn't mean, that you should never use float.

    – SeM
    56 mins ago














12












12








12


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 1 hour ago









Dmitry Bychenko

107k1092133




107k1092133










asked 2 hours ago









YaoqingYaoqing

902




902








  • 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
    2 hours ago








  • 1





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

    – Christopher
    1 hour ago






  • 1





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

    – Jan S.
    1 hour ago






  • 3





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

    – SeM
    1 hour ago






  • 2





    @i486 Again, that doesn't mean, that you should never use float.

    – SeM
    56 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
    2 hours ago








  • 1





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

    – Christopher
    1 hour ago






  • 1





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

    – Jan S.
    1 hour ago






  • 3





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

    – SeM
    1 hour ago






  • 2





    @i486 Again, that doesn't mean, that you should never use float.

    – SeM
    56 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
2 hours 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
2 hours 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
1 hour ago





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

– Christopher
1 hour ago




1




1





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

– Jan S.
1 hour ago





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

– Jan S.
1 hour ago




3




3





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

– SeM
1 hour ago





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

– SeM
1 hour ago




2




2





@i486 Again, that doesn't mean, that you should never use float.

– SeM
56 mins ago





@i486 Again, that doesn't mean, that you should never use float.

– SeM
56 mins ago












3 Answers
3






active

oldest

votes


















17














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
    1 hour ago






  • 4





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

    – Dmitry Bychenko
    1 hour ago






  • 1





    @GonzaloLorieto stackoverflow.com/questions/618535/…

    – Camilo Terevinto
    1 hour ago






  • 1





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

    – SeM
    1 hour ago



















7














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 from it:



    float ff = (float)31.15;

    double dd = 31.15;

    var frst = Math.Round(
    double.Parse(ff.ToString(CultureInfo.InvariantCulture), 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 because the conversion from float to double is avoided.






    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









      17














      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
        1 hour ago






      • 4





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

        – Dmitry Bychenko
        1 hour ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        1 hour ago






      • 1





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

        – SeM
        1 hour ago
















      17














      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
        1 hour ago






      • 4





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

        – Dmitry Bychenko
        1 hour ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        1 hour ago






      • 1





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

        – SeM
        1 hour ago














      17












      17








      17







      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 1 hour ago









      Dmitry BychenkoDmitry Bychenko

      107k1092133




      107k1092133













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

        – Gonzalo Lorieto
        1 hour ago






      • 4





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

        – Dmitry Bychenko
        1 hour ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        1 hour ago






      • 1





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

        – SeM
        1 hour ago



















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

        – Gonzalo Lorieto
        1 hour ago






      • 4





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

        – Dmitry Bychenko
        1 hour ago






      • 1





        @GonzaloLorieto stackoverflow.com/questions/618535/…

        – Camilo Terevinto
        1 hour ago






      • 1





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

        – SeM
        1 hour ago

















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

      – Gonzalo Lorieto
      1 hour ago





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

      – Gonzalo Lorieto
      1 hour ago




      4




      4





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

      – Dmitry Bychenko
      1 hour ago





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

      – Dmitry Bychenko
      1 hour ago




      1




      1





      @GonzaloLorieto stackoverflow.com/questions/618535/…

      – Camilo Terevinto
      1 hour ago





      @GonzaloLorieto stackoverflow.com/questions/618535/…

      – Camilo Terevinto
      1 hour ago




      1




      1





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

      – SeM
      1 hour ago





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

      – SeM
      1 hour ago













      7














      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






























        7














        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




























          7












          7








          7







          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 1 hour ago

























          answered 1 hour 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 from it:



              float ff = (float)31.15;

              double dd = 31.15;

              var frst = Math.Round(
              double.Parse(ff.ToString(CultureInfo.InvariantCulture), 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 because the conversion from float to double is avoided.






              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 from it:



                float ff = (float)31.15;

                double dd = 31.15;

                var frst = Math.Round(
                double.Parse(ff.ToString(CultureInfo.InvariantCulture), 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 because the conversion from float to double is avoided.






                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 from it:



                  float ff = (float)31.15;

                  double dd = 31.15;

                  var frst = Math.Round(
                  double.Parse(ff.ToString(CultureInfo.InvariantCulture), 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 because the conversion from float to double is avoided.






                  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 from it:



                  float ff = (float)31.15;

                  double dd = 31.15;

                  var frst = Math.Round(
                  double.Parse(ff.ToString(CultureInfo.InvariantCulture), 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 because the conversion from float to double is avoided.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 1 min ago

























                  answered 1 hour 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

                      Statuo de Libereco

                      Tanganjiko

                      Liste der Baudenkmäler in Enneberg