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

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

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

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

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

#1楼 票数:13

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

  • 如果你有权访问一个像样的C99数学库,你可以使用nextafter (及其float和long double变体, nextafterfnextafterl ); nexttoward家族(其需要相当长的双作为第二个参数)。

  • 如果你写Fortran,你有nearest内在可用

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

#2楼 票数: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的值

返回:

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

#3楼 票数:5

正如Thorsten S.所说,这可以通过BitConverter类来完成,但是他的方法假定DoubleToInt64Bits方法返回double的内部字节结构,而不是。 该方法返回的整数实际上返回0和你之间的可表示双精度数。 即最小的正双数由1表示,下一个最大的双数为2,等等。负数从long.MinValue开始long.MinValue并远离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);
}

这不涉及InfinityNaN,但你可以检查这些并按照你喜欢的方式处理它们,如果你担心的话。

#4楼 票数:2

是的,有一种方法。 在C#中:

       public static double getInc (double d)
        {
                // Check for special values
                if (double.IsPositiveInfinity(d) || double.IsNegativeInfinity(d))
                    return d;
                if (double.IsNaN(d))
                    return d;

                // Translate the double into binary representation
                ulong bits = (ulong)BitConverter.DoubleToInt64Bits(d);
                // Mask out the mantissa bits
                bits &= 0xfff0000000000000L;
                // Reduce exponent by 52 bits, so subtract 52 from the mantissa.
                // First check if number is great enough.
                ulong testWithoutSign = bits & 0x7ff0000000000000L;
                if (testWithoutSign > 0x0350000000000000L)
                  bits -= 0x0350000000000000L;
                else
                  bits = 0x0000000000000001L;
                return BitConverter.Int64BitsToDouble((long)bits);
}

可以增加和减少增加。

#5楼 票数:1

关于epsilon函数,它是对二进制double可能的十进制值的近似值的估计。 这是因为,对于非常大的正或负十进制数或非常小的正或负十进制数,它们中的许多映射到与double相同的二进制表示。 尝试一些非常非常大或非常非常小的十进制数,从它们创建双精度然后转换回十进制数。 你会发现你不会得到相同的十进制数,而是最接近的那个。

对于接近的值(接近相对于双倍数可以表示的巨大的十进制值范围)1或-1,epsilon将为零或非常非常小。 对于逐渐朝向+或 - 无穷大或零的值,epsilon将开始增长。 在非常接近零或无穷大的值处,epsilon将非常大,因为这些范围中的十进制值的可用二进制表示非常非常稀疏。

#6楼 票数:1

我不确定我是否正在关注你的问题。 当然,IEEE标准完全统一的吗? 例如,请查看维基百科文章中有关双精度数字的摘录。

3ff0 0000 0000 0000   = 1
3ff0 0000 0000 0001   = 1.0000000000000002, the next higher number > 1
3ff0 0000 0000 0002   = 1.0000000000000004

只是以二进制或十六进制表示递增最低有效位有什么问题?

至于特殊数字(无穷大,NaN等),它们定义得很好,而且它们并不是很多。 限制类似地定义。

既然你已经明白了这一点,我希望自己有一个错误的结局。 如果这不足以解决您的问题,您是否可以尝试澄清您想要实现的目标? 你的目标是什么?

  ask by Mark T translate from so

未解决问题?本站智能推荐:

2回复

获得下一个最小的双号

作为单元测试的一部分,我需要测试一些边界条件。 一种方法接受System.Double参数。 有没有办法获得下一个最小的双值? (即将尾数减1个单位值)? 我考虑使用Double.Epsilon但这是不可靠的,因为它只是从零开始的最小增量,因此不适用于较大的值(即99999999
3回复

IEEE-754的浮点数,双精度数和四进制数是否保证精确表示-2,-1,-0、0、1、2?

所有在标题:不IEEE-754 float , double和quad保证确切表示-2 , -1 , -0 , 0 , 1 , 2 ?
1回复

使用C查找下一个IEEE 754可表示的数字(朝向-INF)? [重复]

这个问题在这里已有答案: 你如何找到浮点数最接近的非等值? [重复] 3个答案 我正在尝试编写一个函数,它接受一个32位浮点数(已从32位二进制字符串转换)并返回32位二进制的前一个可表示的浮点数。 到目前为止,我已经从二进制转换为浮点数,但是我很难理解如何找到
5回复

不同编译器的双精度不同行为

我的代码很简单 double d = 405, g = 9.8, v = 63; double r = d * g / (v * v); printf("%s\n",(r>1.0)?"GT":"LE"); 这是我的结果 g ++ - mingw32-v4.8.1:LE (
1回复

如何在python中访问IEEE 754中定义的舍入模式?

我需要在Python中精确计算单精度浮点数。 我尝试过的选项是decimal.Decimal和numpy.float32 。 但是, Decimal不基于IEEE 754,而float32不允许使用舍入模式。 令人惊讶的是,舍入模式是IEEE 754的标准功能,但在Python中没有内
1回复

这是IEEE数学中舍入误差的直观表示吗

在Wolfram Alpha中: 当减法操作数的数量级相差超过2^24 (32位浮点数)时,这是否会在解决方案中出现舍入误差? 链接: 等式图 链接: 每位计算机科学家都应了解的浮点算法
2回复

使用减法引起ieee-754浮点格式的下溢

这似乎很基本,但是我在回答以下问题时遇到很多麻烦: 给出以IEEE754格式表示的两个数字X和Y,以便计算XY将导致下溢。 据我了解,每项操作都可能导致下溢,但在我的生活中,我找不到一个减法示例。 请帮忙!!! 谢谢
1回复

再次浮点精度

昨天我问一个问题,为什么我是在一个浮点运算精度损失。 我收到一个关于如何在x87寄存器中保存中间结果的答案。 这很有帮助,但有些细节仍在逃避。 这是我在上一个问题中提出的程序的变体,我在调试模式下使用VC ++ 2010 Express。 这输出 根据IEEE标准,第一个值