下一个更高/更低的IEEE双精度数

Mar*_*k T 21 double ieee-754 floating-point-precision

我正在进行高精度的科学计算.在寻找各种效果的最佳表示时,我不断提出想要获得下一个更高(或更低)双精度数的理由.基本上,我想要做的是在double的内部表示中添加一个最低有效位.

难点在于IEEE格式不完全一致.如果要使用低级代码并实际将一个代码添加到最低有效位,则生成的格式可能不是下一个可用的双精度型.例如,它可能是一个特殊的案例编号,例如PositiveInfinity或NaN.还有一些次正常值,我不认为这些值,但它们似乎具有与"正常"模式不同的特定位模式.

可以使用"epsilon"值,但我从未理解其定义.由于double值不是均匀间隔,因此不能将单个值添加到double以产生下一个更高的值.

我真的不明白为什么IEEE没有指定一个函数来获得下一个更高或更低的值.我不可能是唯一需要它的人.

有没有办法获得下一个值(没有某种类型的循环尝试添加更小和更小的值).

F'x*_*F'x 13

有一些功能可以完全实现,但它们可能取决于您使用的语言.两个例子:

  • 如果你有权访问一个体面的C99数学库,你可以使用nextafter(及其float和long double变体,nextafterfnextafterl); 或nexttoward家庭(作为第二个论点取长双).

  • 如果你写Fortran,你就有了nearest内在的可用性

如果您无法直接从您的语言访问这些内容,您还可以查看它们是如何在免费提供的情况下实现的,例如本文.


Jim*_*Jim 8

大多数语言都具有内部函数或库函数,用于获取下一个或上一个单精度(32位)和/或双精度(64位)数.

对于32位和64位浮点运算的用户,对基本结构的充分理解对于避免它们的某些危险非常有用.IEEE标准统一适用,但仍然为实施者留下了许多细节.因此,基于机器字表示的位操作的平台通用解决方案可能是有问题的并且可能取决于诸如字节序等的问题.虽然了解它可以或应该在位级别工作的所有详细信息可能会展示出智能实力,但仍然可以更好地使用为每个平台量身定制的内在或库解决方案,并在支持的平台上具有通用API.

我注意到了C#和C++的解决方案.以下是Java的一些内容:

Math.nextUp:

public static double nextUp(double d):

  • 返回正无穷大方向上与d相邻的浮点值.该方法在语义上等同于nextAfter(d,Double.POSITIVE_INFINITY); 但是,nextUp实现可能比其等效的nextAfter调用运行得更快.

特别案例:

  • 如果参数是NaN,则结果为NaN.
  • 如果参数为正无穷大,则结果为正无穷大.
  • 如果参数为零,则结果为Double.MIN_VALUE

参数:

  • d - 开始浮点值

返回:

  • 相邻的浮点值更接近正无穷大.

public static float nextUp(float f):

  • 返回正无穷大方向上与f相邻的浮点值.此方法在语义上等同于nextAfter(f,Float.POSITIVE_INFINITY); 但是,nextUp实现可能比其等效的nextAfter调用运行得更快.

特别案例:

  • 如果参数是NaN,则结果为NaN.
  • 如果参数为正无穷大,则结果为正无穷大.
  • 如果参数为零,则结果为Float.MIN_VALUE

参数:

  • f - 开始浮点值

返回:

  • 相邻的浮点值更接近正无穷大.

接下来的两个使用起来有点复杂.然而,朝向零或朝向正或负无穷大的方向似乎更可能和有用的用途.另一个用途是看到两个值之间存在中间值.可以通过循环和计数器确定两个值之间存在多少.此外,似乎它们与nextUp方法一起可能对for循环中的递增/递减有用.

Math.nextAfter:

public static double nextAfter(双启动,双向)

  • 返回第二个参数方向上第一个参数旁边的浮点数.如果两个参数比较相等,则返回第二个参数.

特别案例:

  • 如果任一参数是NaN,则返回NaN.
  • 如果两个参数都是带符号的零,则方向返回不变(如果参数比较相等,则返回第二个参数的要求暗示).
  • 如果start是±Double.MIN_VALUE并且direction有一个值,使得结果应该具有较小的幅度,则返回与start具有相同符号的零.
  • 如果start为无穷大且direction有一个值,使得结果的幅度较小,则返回Double.MAX_VALUE,其符号与start相同.
  • 如果start等于±Double.MAX_VALUE并且direction具有一个值,使得结果应该具有更大的幅度,则返回具有与start相同的符号的无穷大.

参数:

  • start - 启动浮点值
  • direction - 指示应该返回start的邻居或start的值

返回:

  • 相邻的浮点数在方向方向上开始.

public static float nextAfter(float start,double direction)

  • 返回第二个参数方向上第一个参数旁边的浮点数.如果两个参数比较为相等,则返回与第二个参数等效的值.

特别案例:

  • 如果任一参数是NaN,则返回NaN.
  • 如果两个参数都是带符号的零,则返回等于direction的值.
  • 如果start是±Float.MIN_VALUE并且direction有一个值,结果应该具有较小的幅度,则返回与start符号相同的零.
  • 如果start为无穷大且direction有一个值,使得结果的幅度较小,则返回与start相同符号的Float.MAX_VALUE.
  • 如果start等于±Float.MAX_VALUE且方向具有一个值,使得结果应具有更大的幅度,则返回与start相同的无穷大.

参数:

  • start - 启动浮点值
  • direction - 指示应该返回start的邻居或start的值

返回:

  • 相邻的浮点数在方向方向上开始.


Han*_*ank 5

正如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)

这不涉及InfinityNaN,但你可以检查这些,并与他们打交道,只要你喜欢,如果你担心它.


Mat*_*mas 2

C# 现在有System.Math.BitIncrementBitDecrement从 .Net Core 3.0+ 开始,/功能。

根据微软的注释

[这些对应] 和nextUpIEEEnextDown操作。它们返回(分别)大于或小于输入的最小浮点数。例如,Math.BitIncrement(0.0)将返回double.Epsilon.

  • 好吧,12 年后终于有了一种有把握(而且简单)的方法来做到这一点。谢谢,马特。 (2认同)