例如:不能再精确表示为double的最小uint32_t值是多少?等等的。如何计算这些值?
double
uint32_t
vi4fp9gy1#
不能再精确表示为double的最小uint32_t值是多少?所有uint32_t都可以精确地表示为double,因为C指定DBL_DIG >= 10导致C编码 * 精确 * 至少所有连续整数值[-1010到+1010]。这包括所有的uint32_t。如何计算这些值?参见C规范。可精确编码为浮点类型的整数值的最小连续范围由C主要通过以下方式指定:
DBL_DIG >= 10
FLT_DIG 6 DBL_DIG 10 LDBL_DIG 10
在float的情况下,所有6个十进制数字整数都可以表示[-999,999.0到+999,999.0],包括+/-1,000,000。从零开始向下,第一个不能表示为float的负整数值是-1,000,001。这是FLT_RADIX == 10时的最小范围,几乎不再存在。当FLT_RADIX == 2(非常常见)时,有效位中的二进制位数p为:
float
FLT_RADIX == 10
FLT_RADIX == 2
p
(p-1)*log10(2) >= xxx_DIG
对float,p求解该方程至少为20。使用p == 20,float可以精确地编码整数[-220到+220]或[-1,048,576到+1,048,576]。最低规格也就这么多了。
p == 20
常用限额
典型的float具有符号位和24个二进制数字,其范围比C规范的最小值更宽。它精确地编码整数[-224到+224]。第一个不可表示的负整数值:-224-1或-16777217。
ua4mk5z42#
float和double是什么取决于编译器,它基于体系结构进行选择。在x86或x86-64上,float可能是IEEE单精度浮点数,double可能是IEEE双精度浮点数。| 类型|连续范围可表示整数(包含边界)|此范围的大小|| - -----|- -----|- -----|| 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。1.次法线(极小的数字)的精度较低。
tf7tbtn23#
1.你的问题中有一个主要的矛盾:你说的是“小数点”数据类型,但后来提到了“双精度”。double,在绝大多数可用的实现中,不是小数点类型,而是二进制点类型(IEEE 754 64位十进制)。你可以在互联网和文献中更详细地了解它们的区别。下面我将假设二进制double,而不是(实际上很少出现和使用)真正的十进制类型。2.这很简单,但有点棘手:))我将假设您引用的平台本机实现IEEE 754,float是32位二进制IEEE数,double是64位二进制IEEE数。在这种情况下,float有24位尾数,前导为1(我们在这里不计算非正规值),我们需要最小的值,* 不包括前导尾随零 *,不适合24位。(无需检查问题的指数范围。)对于以下内容,“0 b”是二进制前缀,并且“”是幂运算符。16777215 = 224-1是0 b1111111111111111111111(24个连续的1)。很合适。16777216 = 224是0 b1000000000000000000000(1和24个连续的0)。很合适。16777217 = 224+1是0 b10000000000000000000001(1,23个连续的0和1)。它不合适。“浮动”可以表示:...,16777214,16777215,16777216,16777218,16777220,16777222...因此,从16777216 = 2**24开始,可表示值之间的步长为2。因此,最小的无符号整数,不能用“float”表示,是16777217。在其他情况下,不需要复制所有这些长字符串位-使用具有53位尾数的double,这将是非常麻烦的。我希望这个原则能够得到很好的体现。对于您的具体示例,这意味着任何uint32_t值都可以在double中精确表示,但不能在float中表示。3.此外,对于uint32_t和double,您可以只检查声明的准确性。uint32_t最多为10位十进制数字(保证为9位)。double最多需要17位十进制数字来精确表示任何值,并且保证在其中表示15位。范围之间存在明显差异,因此无需进行更精确的边界检查。
3条答案
按热度按时间vi4fp9gy1#
不能再精确表示为
double
的最小uint32_t
值是多少?所有
uint32_t
都可以精确地表示为double
,因为C指定DBL_DIG >= 10
导致C编码 * 精确 * 至少所有连续整数值[-1010到+1010]。这包括所有的uint32_t
。如何计算这些值?
参见C规范。
可精确编码为浮点类型的整数值的最小连续范围由C主要通过以下方式指定:
在
float
的情况下,所有6个十进制数字整数都可以表示[-999,999.0到+999,999.0],包括+/-1,000,000。从零开始向下,第一个不能表示为float
的负整数值是-1,000,001。这是FLT_RADIX == 10
时的最小范围,几乎不再存在。当
FLT_RADIX == 2
(非常常见)时,有效位中的二进制位数p
为:对
float
,p
求解该方程至少为20。使用p == 20
,float
可以精确地编码整数[-220到+220]或[-1,048,576到+1,048,576]。最低规格也就这么多了。
常用限额
典型的
float
具有符号位和24个二进制数字,其范围比C规范的最小值更宽。它精确地编码整数[-224到+224]。第一个不可表示的负整数值:-224-1或-16777217。ua4mk5z42#
float
和double
是什么取决于编译器,它基于体系结构进行选择。在x86或x86-64上,float
可能是IEEE单精度浮点数,double
可能是IEEE双精度浮点数。| 类型|连续范围可表示整数(包含边界)|此范围的大小|
| - -----|- -----|- -----|
| 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。
1.次法线(极小的数字)的精度较低。
tf7tbtn23#
1.你的问题中有一个主要的矛盾:你说的是“小数点”数据类型,但后来提到了“双精度”。
double
,在绝大多数可用的实现中,不是小数点类型,而是二进制点类型(IEEE 754 64位十进制)。你可以在互联网和文献中更详细地了解它们的区别。下面我将假设二进制
double
,而不是(实际上很少出现和使用)真正的十进制类型。2.这很简单,但有点棘手:))
我将假设您引用的平台本机实现IEEE 754,
float
是32位二进制IEEE数,double
是64位二进制IEEE数。在这种情况下,float
有24位尾数,前导为1(我们在这里不计算非正规值),我们需要最小的值,* 不包括前导尾随零 *,不适合24位。(无需检查问题的指数范围。)对于以下内容,“0 b”是二进制前缀,并且“”是幂运算符。
16777215 = 224-1是0 b1111111111111111111111(24个连续的1)。很合适。
16777216 = 224是0 b1000000000000000000000(1和24个连续的0)。很合适。
16777217 = 224+1是0 b10000000000000000000001(1,23个连续的0和1)。它不合适。
“浮动”可以表示:...,16777214,16777215,16777216,16777218,16777220,16777222...因此,从16777216 = 2**24开始,可表示值之间的步长为2。
因此,最小的无符号整数,不能用“float”表示,是16777217。
在其他情况下,不需要复制所有这些长字符串位-使用具有53位尾数的
double
,这将是非常麻烦的。我希望这个原则能够得到很好的体现。对于您的具体示例,这意味着任何uint32_t
值都可以在double
中精确表示,但不能在float
中表示。3.此外,对于
uint32_t
和double
,您可以只检查声明的准确性。uint32_t
最多为10位十进制数字(保证为9位)。double
最多需要17位十进制数字来精确表示任何值,并且保证在其中表示15位。范围之间存在明显差异,因此无需进行更精确的边界检查。