当我运行以下代码时,我在两行上都打印0:
Double a = 9.88131291682493E-324;
Double b = a*0.1D;
Console.WriteLine(b);
Console.WriteLine(BitConverter.DoubleToInt64Bits(b));
Run Code Online (Sandbox Code Playgroud)
如果操作结果超出范围,我希望得到Double.NaN.相反,我得到0.它看起来能够检测到这种情况发生时我必须检查:
那是相当笨拙的.有没有更好的办法?Double.NaN的目的是什么?我假设某些操作一定要归还它,当然设计师并没有把它放在那里以防万一?这可能是BCL中的一个错误吗?(我知道不太可能,但是,这就是为什么我想了解Double.NaN应该如何工作)
更新
顺便说一句,这个问题不是双重的.十进制暴露它们都是一样的:
Decimal a = 0.0000000000000000000000000001m;
Decimal b = a* 0.1m;
Console.WriteLine(b);
Run Code Online (Sandbox Code Playgroud)
这也给出了零.
在我的情况下,我需要加倍,因为我需要他们提供的范围(我正在进行概率计算)并且我并不担心精度.
我需要的是能够检测到我的结果何时停止意味着什么,也就是当计算将值降低到如此之低时,它就不能再用double表示.
有没有实用的方法来检测这个?
Double 完全按照浮点数规范IEEE 754工作.所以不,它不是BCL中的错误 - 它只是IEEE 754浮点工作的方式.
当然,原因在于它根本不是浮子的设计.相反,你可能想要使用decimal,这是一个精确的十进制数,不像float/ double.
浮点数中有一些特殊值,含义不同:
1f / 0f.-1f / 0f.0f / 0f或Math.Sqrt(-1)但是,正如下面的评论者所指出的那样,decimal实际上确实检查了溢出,过于接近零不会被视为溢出,就像浮点数一样.所以,如果你真的需要检查这一点,你必须使自己*和/方法.但是,对于十进制数字,您不应该非常关心.
如果你需要这种乘法和除法的精度(也就是说,你希望你的除法可以通过乘法来反转),你可能应该使用有理数 - 两个整数(如果需要的话可以是大整数).并使用checked上下文 - 这将在溢出时产生异常.
IEEE 754实际上确实处理了下溢.有两个问题:
因此,如果您真的关心可逆性等,请坚持理性数字.C#与否都decimal不会double起作用.如果你不说精确,你不应该在乎反正下溢-只需选择最低的合理数量,并根据该为"无效"的任何声明; 可能你肯定远离实际的最大精度 - double.Epsilon显然不会有帮助.
你需要的只是epsilon.
这是一个"小数字",足够小,所以你不再感兴趣.
你可以使用:
double epsilon = 1E-50;
Run Code Online (Sandbox Code Playgroud)
每当你的一个因素变得比epislon小时,你就采取行动(例如将其视为0.0)
| 归档时间: |
|
| 查看次数: |
360 次 |
| 最近记录: |