float 计算 : When to Round?

标签 c floating-point rounding ieee-754

我正在用 C 语言使用 float 执行一些计算。我专门处理我得到指数的最低可能单精度值的情况。

假设我的指数是 -126,我必须将它递减。在这种情况下,我不能再低了,所以我需要将尾数右移一次。我知道我应该得到计算的确切答案,然后然后四舍五入(到指定的任何地方)。

我正在考虑这样做(让 M 成为尾数):

M >>= 1;
//round mantissa
  1. 由于我将尾数向右移动并且浮点左侧隐含了 1,我是否需要在移动后修改 M,如:

    M |= (1 << 23)
    

    确保最高有效位为 1?

  2. 在丢失一些信息后四舍五入似乎很奇怪,但这是标准/公认的做法吗?或者我应该通过使用更多位然后然后四舍五入来计算完整结果吗?

最佳答案

对于 float ,有“法线”和“非法线”。

对于“法线”,尾数隐含 1 位,值为 ( 1 + (mantissa >> mantissa_bits) ) << (exponent_value - exponent_bias) .

对于“非正规化”,尾数没有隐含的 1 位,指数始终是其最小值(或比正规化的最小值小 1)并且值为 (mantissa >> mantissa_bits) << (0 - exponent_bias)mantissa >> (exponent_bias + mantissa_bits) .

对于非正规化,当您向右移动时,指数保持不变,而尾数被移动。最低有效位将丢失,但用于舍入尾数(根据舍入模式)。例如。 (假设四舍五入到最近)1011001b >> 5 = 10.11001b = 11b1001001b >> 5 = 10.01001b = 10b .

请注意,非规范化很烦人,并且需要进行特殊情况处理才能影响性能;所以大多数现代 CPU 都有一个特殊的“反规范为零”模式(不符合 IEEE 标准),它只是用 +/- 0 替换任何反规范。

如果您在软件中执行此操作,则使用更大的浮点格式(精度更高)进行所有计算可能会更快,并忽略非正规化(这会降低微小数字的精度)以得到相同的结果精确度低得多。如有必要,您可以在“较大的无反规范化”和“较小的反规范化”格式之间进行转换。具体来说;我很想使用 64 位尾数和没有反正规的 32 位指数,并使用例程将这种内部格式转换为“32 位 float ”和“64 位 double ”。

关于 float 计算 : When to Round?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30541294/

相关文章:

使用定点数学计算 RMS (C)

c++ - 如果它们是 16 字节对齐的,是否可以将 float 直接转换为 __m128?

c++ - 检查 char* 缓冲区是否包含 UTF8 字符?

c# - 如何在 C# 中舍入浮点值?

C++ next float with numeric_limits/epsilon?

c# - 将 float 舍入为 -1、0 或 1

java - A Double 中有多少位小数(Java)

c - 负数和无符号分母的模运算的奇怪结果

algorithm - 定点 Cholesky 算法的优点

python - 如何在 Python 中舍入十六进制值