为什么模运算符不适用于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);
}