提问人:HeapUnderStop 提问时间:5/22/2023 最后编辑:Weather VaneHeapUnderStop 更新时间:5/23/2023 访问量:285
在 C 小数点数据类型中无法精确表示的最小值是什么?
What are the smallest values that can no longer be represented exactly in C decimal point datatypes?
答:
What 和 are 因编译器而异,它根据架构进行选择。在 x86 或 x86-64 上,a 可能是 IEEE 单精度浮点数,也可能是 IEEE 双精度浮点数。float
double
float
double
类型 | 连续 可表示整数 的范围(非独占边界) |
此范围的大小 |
---|---|---|
uint16_t | 0 ..2^16-1 | 2^16 |
uint32_t | 0 ..2^32-1 | 2^32 |
uint64_t | 0 ..2^64-1 | 2^64 |
IEEE单精度 | -2^24 ..2^24 | 2^25+1 |
IEEE双精度 | -2^53 ..2^53 | 2^54+1 |
IEEE 单精度浮点数具有 24 位精度。[1] 它可以准确地表示比上面提到的大得多的数字,但它不能完全代表 2^24+1 或 -2^24-1。
IEEE 双精度浮点数具有 53 位精度。[1] 它可以准确地表示比上面提到的大得多的数字,但它不能完全代表 2^53+1 或 -2^53-1。
- 次正态值(极小数字)的精度较低。
不能再精确表示为 的最小值是多少?
uint32_t
double
所有这些都可以精确地表示为 a,因为 C 指定 C 编码的结果至少是所有连续的整数值 [-10 10 到 +1010]。这包括所有 .uint32_t
double
DBL_DIG >= 10
uint32_t
如何计算这些值?
请参阅 C 规范。
整数值的最小连续范围完全可编码为浮点类型,主要由 C 指定:
FLT_DIG 6
DBL_DIG 10
LDBL_DIG 10
在 的情况下,所有 6 个十进制数字整数都可以表示 [-999,999.0 至 +999,999.0],包括 +/- 1,000,000。从零开始向下,第一个可能无法表示为 a 的负整数值是 -1,000,001。这是 时的最小范围,几乎不存在了。float
float
FLT_RADIX == 10
当(很常见)时,有效位数中的二进制位数为:FLT_RADIX == 2
p
(p-1)*log10(2) >= xxx_DIG
求解这个问题,至少是 20。使用 ,可以精确编码整数 [-2 20 到 +220] 或 [-1,048,576 到 +1,048,576]。float
p
p == 20
float
最低规格就这么多。
公共限制
具有符号位和 24 个二进制数字的典型浮点数
的范围比 C 规范最小值更宽。它精确编码整数 [-224 至 +224]。第一个不可表示的负整数值:-224 - 1 或 -16,777,217。
1. 你的问题有一个主要差异:你说了“小数点”数据类型,但随后提到了“双精度”。
double
,在大多数可用实现中,它不是小数点类型,而是二进制点类型(IEEE754 64 位十进制)。您可能会在互联网和文献中更详细地查看它们之间的区别。
对于以下内容,我将假设二进制而不是(实际上很少存在和使用)真正的十进制类型。double
2. 嗯,很简单,但有点棘手:))
我将假设您引用的平台本机实现了 IEEE754,并且是 32 位二进制 IEEE 编号和 64 位二进制 IEEE 编号。
在本例中,具有前导 1 的 24 位尾数(我们在这里不计算非正态),我们需要最小的值,不包括前导尾随零,不适合 24 位。(无需检查问题的指数范围。float
double
float
对于以下内容,“0b”是二进制前缀,“**”是幂运算符。
16777215 = 2**24-1 是 0b11111111111111111111111111(连续 24 个)。它适合。
16777216 = 2**24 是 0b1000000000000000000000000000 (1 和 24 个连续零)。它适合。
16777217 = 2**24+1 是 0b10000000000000000000000001(1、23 个连续零和 1)。它不合适。
“浮动”可以表示:...、16777214、16777215、16777216、16777218、16777220、16777222......因此,从 16777216 = 2**24 开始,可表示值之间的步长为 2。
因此,在“float”中无法表示的最小无符号整数为 16777217。
无需为其他情况复制所有这些长字符串位 - 使用其 53 位尾数,它会很麻烦。我希望这个原则得到很好的宣布。对于您的具体示例,这意味着任何值都可以用 精确表示,但不能用 表示。double
uint32_t
double
float
3. 此外,您可能只是检查了声明的准确性。 最多 10 位十进制数字(保证 9 位)。 最多需要 17 位十进制数字才能准确表示任何值,并保证 15 位十进制数字表示。范围之间存在明显差异,因此无需进行更精确的边界检查。uint32_t
double
uint32_t
double
评论
uint32_t
uint32_t
double
double
不是小数点数据类型。所有值都完全可以表示为(在符合 IEEE-754 的实现中)。uint32_t
double
double
double
uint32_t
DBL_DIG >= 10