Why is modulus operator not working for double in c#?

前端 未结 6 1053
粉色の甜心
粉色の甜心 2020-11-30 10:21

Consider this:

double x,y;
x =120.0;
y = 0.05;

double z= x % y;

I tried this and expected the result to be 0, but it came out 0.04933333.<

相关标签:
6条回答
  • 2020-11-30 10:52

    http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems can help you understand why you get these "strange" results. There's a particular precision that floating point numbers can have. Just try these queries and have a look at the results:

    0.5 in base 2

    0.05 in base 2

    0 讨论(0)
  • 2020-11-30 10:54

    This is what we use.. :)

     public double ModuloOf(double v1, double v2)
        {
            var mult = 0;
    
            //find number of decimals
            while (v2 % 1 > 0)
            {
                mult++;
                v2 = v2 * 10;
            }
    
            v1 = v1 * Math.Pow(10, mult);
    
            var rem = v1 % v2;
            return rem / Math.Pow(10, mult);
        }
    
    0 讨论(0)
  • 2020-11-30 11:02

    Because of its storage format, doubles cannot store every values exactly as is is entered or displayed. The human representation of numbers is usually in decimal format, while doubles are based on the dual system.

    In a double, 120 is stored precisely because it's an integer value. But 0.05 is not. The double is approximated to the closest number to 0.05 it can represent. 0.5 is a power of 2 (1/2), so it can be stored precisely and you don't get a rounding error.

    To have all numbers exactly the same way you enter / display it in the decimal system, use decimal instead.

    decimal x, y;
    x = 120.0M;
    y = 0.05M;
    
    decimal z = x % y;  // z is 0
    
    0 讨论(0)
  • 2020-11-30 11:02

    Modulus should only be used with integer. The remainder come from an euclidean division. With double, you can have unexpected results.

    See this article

    0 讨论(0)
  • 2020-11-30 11:11

    You could do something like:

    double a, b, r;
    
    a = 120;
    b = .05;
    
    r = a - Math.floor(a / b) * b;
    

    This should help ;)

    0 讨论(0)
  • 2020-11-30 11:12

    I believe if you tried the same with decimal it would work properly.

    0 讨论(0)
提交回复
热议问题