你有多大的数字可以存储在double中并浮动在c中?

时间:2015-07-10 11:47:25

标签: c floating-point sizeof

我正在试图弄清楚我可以使用多大的数字作为浮点数和double。但它不存储我预期的方式,除了整数值。 double应该保存8个字节的信息,足以容纳变量a,但它不能保持正确。它显示1234567890123456768,其中最后2位数字不同。当我在浮点变量214783648的最后一位数中存储b或任何数字时,它会显示相同的值214783648。这应该是极限。那是怎么回事?

double a;
float b;
int c;
a = 1234567890123456789;
b = 2147483648;
c = 2147483647;
printf("Bytes of double: %d\n", sizeof(double));
printf("Bytes of integer: %d\n", sizeof(int));
printf("Bytes of float: %d\n", sizeof(float));

printf("\n");

printf("You can count up to %.0f in 4 bytes\n", pow(2,32));
printf("You can count up to %.0f with + or - sign in 4 bytes\n", pow(2,31));
printf("You can count up to %.0f in 4 bytes\n", pow(2,64));
printf("You can count up to %.0f with + or - sign in in 8 bytes\n", pow(2,63));

printf("\n");

printf("double number: %.0f\n", a);
printf("floating point: %.0f\n", b);
printf("integer: %d\n", c);

return 0;

6 个答案:

答案 0 :(得分:8)

对于FLT_MAX和{{1},可以存储在浮点类型中的最大(有限)数的问题的答案是DBL_MAXfloat分别。

但是,这并不意味着该类型可以精确地表示每个较小的数字或整数(事实上,甚至不是接近)。

首先,您需要了解浮点数的所有位都不是“相等”。浮点数具有指数(8位IEEE-754标准doublefloat中的11位)和尾数(23和double中的52位和float分别)。通过将尾数(其具有隐含的前导1位和二进制点)乘以2 指数(在对指数进行归一化之后;其二进制值不直接使用)来获得该数字。还有一个单独的符号位,因此以下内容也适用于负数。

当指数改变时,尾数的连续值之间的距离也改变,即,指数越大,浮点数的连续可表示值越大。因此,您可以精确地存储给定幅度的一个数字,但不能存储“下一个”数字。还应该记住,一些看似简单的分数不能用任意数量的二进制数字精确表示(例如,double,十分之一,是二进制的无限重复序列,如1/10,三分之一,是小数)。

当涉及到整数时,您可以精确地表示最多2个 mantissa_bits + 1 幅度的每个整数。因此,IEEE-754 1/3可以表示最多2 24 float最多2 53 的所有整数(在这些中的后半部分)范围连续的浮点值恰好是一个整数,因为整个尾数仅用于整数部分)。可以表示单个较大的整数,但它们间隔不止一个整数,即,您可以表示某些整数大于2 mantissa_bits + 1 但是每个整数只能达到那个数量级。

例如:

double

输出:

float f = powf(2.0f, 24.0f);
float f1 = f + 1.0f, f2 = f1 + 2.0f;
double d = pow(2.0, 53.0);
double d1 = d + 1.0, d2 = d + 2.0;
(void) printf("2**24 float = %.0f, +1 = %.0f, +2 = %.0f\n", f, f1, f2);
(void) printf("2**53 double = %.0f, +1 = %.0f, +2 = %.0f\n", d, d1, d2);

正如您所看到的,将2**24 float = 16777216, +1 = 16777216, +2 = 16777218 2**53 double = 9007199254740992, +1 = 9007199254740992, +2 = 9007199254740994 添加到2 mantissa_bits + 1 没有任何区别,因为结果不可表示,但添加1会产生正确答案(如它发生了,在这个数量上,可表示的数字是两个整数,因为乘数已加倍)。

TL; DR IEE-754 2可以精确地表示最多2 24 float最多2 53 的所有整数,但是只有一些更大的整数(可表示值的间距取决于幅度)。

答案 1 :(得分:7)

sizeof(double)8,为true,但double也需要一些位来存储 exponent 部分。

假设使用IEEE-754,double可以精确地表示最多2 53 的整数,小于1234567890123456789

另见Double-precision floating-point format

答案 2 :(得分:2)

您可以使用常量来了解限制:

FLT_MAX
DBL_MAX
LDBL_MAX

From CPP reference

答案 3 :(得分:1)

sizeof对象仅报告它占用的内存空间。它不显示有效的范围。很可能有一个unsigned int例如2 ** 16(65536)可能的值占用32位内存。

对于floating point个对象,它更难。它们由(简化的)两个字段组成:整数尾数和指数(参见链接文章中的详细信息)。两者都有固定的宽度。

由于尾​​数只有一个有限的范围,所以尾随位被截断或舍入,并且如果需要,则更正指数。这是一个永远不应该使用浮点类型来存储货币等精确值的原因之一。

十进制(注意:计算机使用二进制表示),尾数为4位数:

1000 --> 1.000e3
12345678 --> 1.234e7

您的实现的参数在float.h中定义,类似于limits.h,它提供整数参数。

答案 4 :(得分:0)

您可以通过打印存储在' limits.h'中的限制来打印标准POD类型的实际限制。头文件(对于C ++,等效的是' std :: numeric_limits'标识符,如下所示: enter link description here

由于硬件不能分别与浮动类型一起工作,实际上硬件不能代表浮动类型,硬件使用硬件的位长来表示浮动类型。由于您没有浮动类型的无限长度,因此您只能显示/呈现特定精度的双变量。大多数硬件用于浮动类型表示IEEE-754标准。

为了获得更高的精确度,您可以尝试长时间的双倍' (取决于硬件,这可能是两倍的精度),AVX,SSE寄存器,大数字库或你自己做。

答案 5 :(得分:-2)

在Linux上,#include <float.h>

在Windows上,[person, company, city].forEach(function(fn) { fn.name(); });

有一个相当全面的定义列表