Mar*_*k T 21 double ieee-754 floating-point-precision
我正在进行高精度的科学计算.在寻找各种效果的最佳表示时,我不断提出想要获得下一个更高(或更低)双精度数的理由.基本上,我想要做的是在double的内部表示中添加一个最低有效位.
难点在于IEEE格式不完全一致.如果要使用低级代码并实际将一个代码添加到最低有效位,则生成的格式可能不是下一个可用的双精度型.例如,它可能是一个特殊的案例编号,例如PositiveInfinity或NaN.还有一些次正常值,我不认为这些值,但它们似乎具有与"正常"模式不同的特定位模式.
可以使用"epsilon"值,但我从未理解其定义.由于double值不是均匀间隔,因此不能将单个值添加到double以产生下一个更高的值.
我真的不明白为什么IEEE没有指定一个函数来获得下一个更高或更低的值.我不可能是唯一需要它的人.
有没有办法获得下一个值(没有某种类型的循环尝试添加更小和更小的值).
大多数语言都具有内部函数或库函数,用于获取下一个或上一个单精度(32位)和/或双精度(64位)数.
对于32位和64位浮点运算的用户,对基本结构的充分理解对于避免它们的某些危险非常有用.IEEE标准统一适用,但仍然为实施者留下了许多细节.因此,基于机器字表示的位操作的平台通用解决方案可能是有问题的并且可能取决于诸如字节序等的问题.虽然了解它可以或应该在位级别工作的所有详细信息可能会展示出智能实力,但仍然可以更好地使用为每个平台量身定制的内在或库解决方案,并在支持的平台上具有通用API.
我注意到了C#和C++的解决方案.以下是Java的一些内容:
Math.nextUp:
public static double nextUp(double d):
特别案例:
参数:
返回:
public static float nextUp(float f):
特别案例:
参数:
返回:
接下来的两个使用起来有点复杂.然而,朝向零或朝向正或负无穷大的方向似乎更可能和有用的用途.另一个用途是看到两个值之间存在中间值.可以通过循环和计数器确定两个值之间存在多少.此外,似乎它们与nextUp方法一起可能对for循环中的递增/递减有用.
Math.nextAfter:
public static double nextAfter(双启动,双向)
特别案例:
参数:
返回:
public static float nextAfter(float start,double direction)
特别案例:
参数:
返回:
正如Thorsten S.所说,这可以通过BitConverter类完成,但是他的方法假定该DoubleToInt64Bits方法返回它的内部字节结构double,而不是.该方法返回的整数实际上返回0和你之间的可表示双精度数.即最小的正双峰由1表示,下一个最大的双精度为2,等等.负数long.MinValue从0d 开始并远离0d.
所以你可以这样做:
public static double NextDouble(double value) {
// Get the long representation of value:
var longRep = BitConverter.DoubleToInt64Bits(value);
long nextLong;
if (longRep >= 0) // number is positive, so increment to go "up"
nextLong = longRep + 1L;
else if (longRep == long.MinValue) // number is -0
nextLong = 1L;
else // number is negative, so decrement to go "up"
nextLong = longRep - 1L;
return BitConverter.Int64BitsToDouble(nextLong);
}
Run Code Online (Sandbox Code Playgroud)
这不涉及Infinity和NaN,但你可以检查这些,并与他们打交道,只要你喜欢,如果你担心它.
C# 现在有System.Math.BitIncrementBitDecrement从 .Net Core 3.0+ 开始,/功能。
根据微软的注释:
[这些对应] 和
nextUpIEEEnextDown操作。它们返回(分别)大于或小于输入的最小浮点数。例如,Math.BitIncrement(0.0)将返回double.Epsilon.
| 归档时间: |
|
| 查看次数: |
2991 次 |
| 最近记录: |