浮点数的计算:何时进行舍入



我正在用C语言执行一些浮点数计算。我专门处理的情况是我得到了指数的最低精度值。

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

我正在考虑做(让M是尾数):

M >>= 1;
//round mantissa
  1. 由于我将尾数向右移动,并且在浮点数的左侧有一个隐含的1,所以我需要在移动后修改M吗?

    M |= (1 << 23)
    

    确保我在最高位上有一个1 ?

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

对于浮点数有"正数"one_answers"反正数"。

对于"normals",尾数有一个隐含的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代替任何反常态。

如果你在软件中这样做,那么使用更大的浮点格式(具有更好的精度)进行所有计算并忽略反常(这会降低微小数字的精度)可能会更快,从而以相同的精度结束,而更少的麻烦。如果有必要,您可以在"不带反常态的较大"one_answers"带反常态的较小"格式之间进行转换。特别地;我很想使用64位尾号和32位指数,没有异常,用例程在这种内部格式之间转换为"32位float"one_answers"64位double"。

最新更新