floor()和ceil()的可表示结果

7

对于浮点类型(float/double/long double)的任意值“v”,C89是否保证floor(v)和ceil(v)的数学精确整数结果是“v”类型的可表示值?

任何后来的C或C++标准是否保证了这一点?

IEEE 754是否保证了这一点?

1个回答

9
这是通过IEEE-754数字的构建来保证的。(要明确一点:C语言不能保证IEEE-754,但下面的分析同样适用于我熟悉的所有其他浮点格式;关键属性是该格式中所有足够大的数字都是整数)。
回想一下,一个正常的IEEE-754数字具有形式±1.xxx...xxx * 2^n,其中有效数字字段(xxx...xxx部分)的宽度由数字类型定义(单精度为23个二进制数字,双精度为52个二进制数字)。在允许范围内的所有指数n的这样的数字都是可表示的。
假设不失一般性,v是正数(如果v是负数,我们可以在下面的分析中交换ceilfloor)。
vk个有效位,并将v写为二进制定点数;有三种可能情况:
情况1:所有有效数字都是整数。当我们写出v时,它看起来像这样:
xxxxxxxxxxxxxxxxxxxxxxxx000000...00000.0

情况1:所有有效数字位都是整数。此时v为整数,因此ceil(v) = floor(v) = v,因此两者均容易表示。

情况2:所有有效数字位都是小数。当我们写出v时,它看起来像:

0.000000...00000xxxxxxxxxxxxxxxxxxxxxxxx

如果v的值在[0,1)范围内,那么floor(v)=0是可以表示的,而ceil(v)要么是零,要么是一,这两个值都可以表示。

情况3:v同时包含整数和小数位:

xxxxxxxxxxxxxx.xxxxxxxxxx

那么floor(v)就是:
xxxxxxxxxxxxxx.

因为我们丢弃了至少一个小数位,所以 floor(v) 最多具有 k-1 个有效位,并且与 v 具有相同的指数,因此它是可表示的。
如果 v 是整数,则 ceil(v) = floor(v) = v,因此 ceil(v) 是可表示的。否则,ceil(v) = floor(v) + 1,因此最多具有 k-1 个有效位,并且也是可表示的。

1
这个问题涉及到IEEE 754,但C标准可能会更加松散。它是否允许某种情况,例如99.9999(或0xff.ffff或二进制11.1111)是最大的可表示有限数字,因此其上取整值虽然是一个具有较少有效数字的整数,但却无法表示? - Eric Postpischil
2
@EricPostpischil:是的,C标准允许这样的类型。话虽如此,所有常见的替代浮点数格式(甚至像旧IBM或UNIVAC这样的稍微奇特的格式)都具有这样的属性,即所有足够大的数字都是整数。 - Stephen Canon
我怀疑对于C语言,即使在非IEEE实现中,floor()和ceil()也保证返回整数值(这是真的吗?)然而,floor()可能会返回比真实整数结果小的整数值,ceil()可能会返回比真实整数结果大的整数值。 - Kristian Spangsege

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接