C++03是否保证`double`可以准确表示较小的整数?

8
C++03标准是否保证double可以精确表示足够小的非零整数?如果不是,那C++11呢?注意,我这里并没有假定符合IEEE标准。

我怀疑答案是否定的,但我很乐意被证明是错误的。所谓“足够小”,指的是某个值被C++03保证,并且可以从通过std::numeric_limits<double>提供的值计算出来。

编辑:显而易见(现在我已经确认),std::numeric_limits<double>::digitsDBL_MANT_DIG是同一回事,std::numeric_limits<double>::digits10DBL_DIG也是同一回事,C++03和C++11都是如此。

此外,对于DBL_MANT_DIGDBL_DIG的含义,C++03推迟到C90,C++11推迟到C99。

C90和C99均声明DBL_DIG的最小允许值为10,即10个十进制数字。

那么问题是什么?这是否意味着double可以精确表示多达10位十进制数字的整数?

如果是这样,那么C99中的DECIMAL_DIG和C99 §5.2.4.2.2 / 12中的以下声明还有什么用呢?

使用DECIMAL_DIG位将(至少)double转换为十进制数,然后再转回去应该是恒等函数。



C99§5.2.4.2.2 / 9中对DBL_DIG的解释如下:
Number of decimal digits, 'q', such that any floating-point
number with 'q' decimal digits can be rounded into a
floating-point number with 'p' radix 'b' digits and back again
without change to the q decimal digits,

    { p * log10(b)              if 'b' is a power of 10
    {
    { floor((p-1) * log10(b))   otherwise

FLT_DIG   6
DBL_DIG   10
LDBL_DIG  10

如果有人能帮助我解包这个文件,我会很高兴。


C99标准(在C++03中是规范性的)在§5.2.4.2.2中给出了许多浮点类型的要求,如果有人愿意解密的话。它可能对某些整数提供某种保证。 - Joseph Mansfield
C99在C++03中是规范性的,这到底意味着什么? - Kristian Spangsege
每当引用时,这意味着它应该被视为全能的真理!在这种情况下,它被引用作为<climits>头文件定义的一部分。基本上是从其他标准中借鉴而来的。 - Joseph Mansfield
@sftrabbit 我看到C99在C++03 [intro.refs]中被提到作为“规范引用”。然而,正如C++03 [intro.scope]中所述,C99不应该被认为是C++03的一部分(至少大多数情况下不是)。特别地,DECIMAL_DIG宏不是C++03的一部分。 - Kristian Spangsege
2个回答

7

好的,3.9.1 [basic.fundamental] 第8段规定:

…… 浮点类型的值表示是由实现定义的。……

至少,实现必须定义它使用的表示。

另一方面,std::numeric_limits<F> 定义了一些成员,这些成员似乎暗示表示形式为 尾数 基数 指数 的某种形式:

  • std::numeric_limits<F>::radix: 指数的基数
  • std::numeric_limtis<F>::digits: radix 数字的数量

我认为这些说明意味着你可以精确地表示范围在 0 ... 基数 数字 - 1 的整数。


我认为这些的模型在C99 5.2.4.2.2/2中定义,“浮点数(x)由以下模型定义:x = s b^e \sum_{k=1}^{p} f_k b^{-k}, e_{min} \leq e \leq e_{max}”。 - dyp
1
举个例子,一方面取min_exponent=100,max_exponent=353,另一方面取min_exponent=-353,max_exponent=-100,其他参数与IEEE 754 binary32相同。对于这两个假设的二进制浮点数系统中的每一个,都无法表示数字3。 - Pascal Cuoq
3
@PascalCuoq说:哦,抱歉。是的,浮点类型的覆盖范围中肯定包括0:min_exponent必须为负数,而max_exponent则必须为正数。 - Dietmar Kühl
@DietmarKühl:对于双精度IEEE-754浮点数,2^53产生的数字约为9007199亿,即16位数字,而对于双精度的std::numeric_limits<double>::digits10返回15位数字,这不是有任何差异吗? - Guillaume Paris
1
@Guillaume07:你只能安全地往返于带有最多... :: digits10位数字的十进制值(即,原始十进制值-> double-> 恢复的十进制值会产生与原始十进制值和恢复的十进制值相同的值)。当使用更多数字时,无法保证往返于此能正常工作,尽管对于某些值仍然可以正常工作。 - Dietmar Kühl
显示剩余3条评论

2
根据C标准中与C++相关的“浮点类型特性<float.h>”,我认为您可以将FLT_RADIXFLT_MANT_DIG组合成有用的信息:尾数中的数字数量以及它们所表示的基数。
例如,对于单精度IEEE754浮点数,它们分别为2和24,因此您应该能够存储绝对值高达2的24次方的整数。

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