Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么模运算符不适用于c#中的双精度?_C#_.net - Fatal编程技术网

为什么模运算符不适用于c#中的双精度?

为什么模运算符不适用于c#中的双精度?,c#,.net,C#,.net,考虑这一点: double x,y; x =120.0; y = 0.05; double z= x % y; 我尝试了这个,期望结果是0,但结果是0.04933333 但是, x =120.0; y = 0.5; double z= x % y; 确实给出了正确的结果0 这里发生了什么 我尝试了Math.IEEERemainder(double,double),但它也没有返回0。这是怎么回事 另外,顺便说一句,在C#?中查找余数最合适的方法是什么?因为它的存储格式,doubles无法准确

考虑这一点:

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

double z= x % y;
我尝试了这个,期望结果是0,但结果是0.04933333

但是,

x =120.0;
y = 0.5;
double z= x % y;
确实给出了正确的结果0

这里发生了什么

我尝试了
Math.IEEERemainder(double,double)
,但它也没有返回0。这是怎么回事


另外,顺便说一句,在C#?

中查找余数最合适的方法是什么?因为它的存储格式,
double
s无法准确地存储输入或显示的每个值。数字的人工表示通常采用十进制格式,而双精度s则基于双精度系统

double
中,
120
被精确地存储,因为它是一个整数值。但是
0.05
不是。双精度近似于它所能表示的最接近
0.05的数字
0.5
2
1/2
)的幂,因此可以精确存储,并且不会出现舍入错误

要使所有数字在十进制系统中的输入/显示方式完全相同,请改用
decimal

decimal x, y;
x = 120.0M;
y = 0.05M;

decimal z = x % y;  // z is 0
可以帮助您理解为什么会得到这些“奇怪”的结果。浮点数有一个特殊的精度。只需尝试以下查询并查看结果:


您可以执行以下操作:

double a, b, r;

a = 120;
b = .05;

r = a - Math.floor(a / b) * b;

这应该会有所帮助;)

模数只能与整数一起使用。其余部分来自欧几里得除法。使用double,您可能会得到意想不到的结果


请参见

我相信,如果您尝试使用
十进制进行相同操作,它将正常工作。

这就是我们使用的:)


了解你想要达到的目标会很有趣。将模与浮点数结合使用从来都不是一个好主意,因为答案已经说明了这一点。(不同的语言,但问题——浮点错误——是相同的)您可以安全地使用带小数的模。双精度总是一个精确的值。确定其值的操作可能不精确<代码>双a=0.1-->
a
的精确值可能与数学0.1略有不同<代码>双b=0.125-->
b
具有与数学0.125相同的精确值。使用
decimal
“可能略有不同的精确值”==不精确仍然是个好主意。@chux:每个数字值都有其分辨率。此上下文中的“精确”表示该值在您输入或显示时准确存储。整数是精确的值。如果键入7(例如,在代码中键入常量),则它不会在后台存储6.9999999999999。小数也一样。双打是不同的。由于其存储格式,它无法准确存储输入/显示的值。双精度值永远不会是准确值,这是绝对的浪费。考虑到C#使用IEEE754,这个答案可能会有相当大的提升。@Bathsheba:实现IEEE754无助于使双精度存储精确的十进制值。有关输入/显示值(使用十进制)与双精度存储格式之间的差异,请参阅我的最后一条评论。如果你不相信我说的话,用问题中的代码自己复制它。
 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);
    }