c语言 怎样精确十进制 浮点数,关于浮点精度:C ++我刚刚读到浮点数是不精确的,并且不存储精确的整数值。 这是什么意思?...

我在二进制级别上考虑这一点。

值1的浮点数和值1的整数将不会编译为(此处省略很多零)

0001

如果它们都编译为这个,那么这种不精确性从何而来。

我正在使用的资源是http://www.cprogramming.com/tutorial/lesson1.html

谢谢。

参见例如 zh_cn.wikipedia.org/wiki/Single-precision_floating-point_format通常用于存储浮点数。 这应该可以回答您的问题。

整数可以用浮点数精确表示。

浮点数可以存储7个有效数字。 因此,当然不能精确存储7位以上的整数值。 1没问题,第一个整数值为16777217。请尝试一下。

阅读Wikipedia之后,您可以在binaryconvert.com/convert_float.html上了解IEEE754浮点。 可以精确存储的示例值(32位浮点数):1、42、0.25。 无法显示的示例:0.4,123456789。玩得开心=)

请参阅:每位计算机科学家都应了解的浮点运算法则

这是可能的。浮点数以指数符号(a * 2 ^ n)表示,其中一些位表示a(有效位数),而某些位表示n(指数)。

由于所谓的鸽子洞原理,您不能唯一地表示浮点值范围内的所有整数。例如,32位浮点数最多可以超过10 ^ 38,但是在32位上,您只能表示2 ^ 32的值-这意味着某些整数将具有相同的表示形式。

现在,当您尝试执行以下操作时会发生什么:

x = 10^38 - (10^38 - 1)

您应该得到1,但可能不会,因为10 ^ 38和10 ^ 38-1彼此之间非常接近,以致计算机必须以相同的方式表示它们。因此,您的1.0f通常为1,但如果此1是计算结果,则可能不是。

这里有些例子。

准确地说:如果整数的二进制表示使用的位数不超过尾数的浮点格式提供的位数再加上一个隐含的一位,则整数可以精确地表示为浮点数。

IEEE浮点数的尾数为23位,添加一个隐式位,并且您可以将任何可用24位表示的整数存储在float中(最大为16777216的整数)。同样,双精度数有52个尾数位,因此它可以存储最多9007199254740992的整数。

超出这一点,IEEE格式将首先忽略奇数,然后是所有不能被4整除的数字,依此类推。因此,即使0xffffff00ul也可以精确地表示为浮点数,而0xffffff01ul则不能。

因此,是的,您可以将整数表示为浮点数,只要它们不超过16e6或9e15限制,您甚至可以期望浮点数格式的整数之间的加法是准确的。

简短的答案:不,整数的浮点表示不是那么简单。

C语言标准为float类型采用的表示形式称为IEEE 754单精度,它可能比大多数人想要研究的更为复杂,但是如果您感兴趣,此链接将对其进行全面描述。

至于整数1的表示,我们可以在这里看到它是如何使用IEEE 754定义的32位base-2单精度格式进行编码的-3f80 0000。

如果int小于某个特定数字,则float将完全存储int,但是如果int足够大,则尾数中将没有足够的位来存储int的所有位。整数。然后假定丢失的位为零。如果丢失的位不为零,则您的int将不等于您的float。

某些高于阈值的整数不能存储在float中。 这些是8 * 1024 * 1024和16 * 1024 * 1024之间的奇数,不是16 * 1024 * 1024和32 * 1024 * 1024之间4的倍数的数字,依此类推。 一些非常大的数字(例如3 * 2 ^ 100)正好存储在float中。

@PascalCuoq:好点。 我已经更新了我的答案以解决此问题。

would a float of value 1 and an integer of value 1 not compile down to (omitting lots of zeros here) 0001

不,浮点数的存储方式类似于0x00000803f,具体取决于精度。

What does this mean?

有些数字不能精确地以二进制形式表示。 二进制形式的O.2看起来像0.00110011001100110011...,它将永远继续(并重复)。 无论您使用多少位存储它,都将永远不够。 这是因为2无法将5整除。 精确表示它的唯一方法是使用比率来存储它。

浮点数的精度有限。 粗略地讲,它们仅在第一个有效非零数字之后存储一定数量的数字,其余的将丢失。 这将导致错误,例如,单精度浮点数100000000000000001和100000000000000002最有可能四舍五入为相同的数字。

您可能还想阅读类似的内容。

结论:

如果您正在编写财务软件,请不要使用浮点数。 使用Bignums,并使用gmp之类的库

0x00000803f-取决于精度和字节序。

与某些具有单一基本数字类型的现代动态类型化编程语言(例如JavaScript或Ruby)相反,C编程语言具有多种。这是因为C反映了在处理器寄存器中表示不同种类数字的不同方式。

要研究不同的表示形式,可以使用union构造,其中可以将相同的数据视为不同的类型。

限定

union {

float x;

int v;

} u;

分配u.x = 1.0f和printf("0x%08x

",u.v)以获得1.0f的32位表示形式作为浮点数。它应该返回0x3f800000而不是人们可能期望的0x00000001。

如前所述,这反映了浮点数作为32位值表示为`

1.0f = 0x3F800000 = 0011.1111.1000.0000.0000.0000.0000.0000 =

0 0111.1111 000.0000.0000.0000.0000.0000 = 0 0x7F 0

这里的三个部分是符号s = 0,指数e = 127和尾数m = 0,并且浮点值计算为

value = s * (1 + m * 2^-23) * 2^(e-127)

通过这种表示,可以精确表示从-16,777,215到16,777,215的任何整数。这是(2 ^ 24-1)的值,因为尾数只有23位。此范围对于许多应用程序来说是不够的,因此float类型不能替代int类型。

double类型的整数的精确表示范围更宽,因为该值占用64位,并且为尾数保留了53位。正是来自

-9,007,199,254,740,991至9,007,199,254,740,991。但是double需要两倍的内存。

困难的另一个来源是分数数字的表示方式。由于不能精确表示十进制小数(0.1f = 0x3dcccccd = 0.10000000149 ...),使用浮点数会破坏常见的代数恒等式。

0.1f * 10 != 1.0f

这可能会造成混淆,并导致难以检测的错误。通常,严格相等不应该与浮点数一起使用。

从代数正确性浮点运算的另一个例子:

float x = 16777217.0f;

float y = 16777215.0f;

x -= 1.0f;

y += 1.0f;

if (y > x) {printf("16777215.0 + 1.0 > 16777217.0 - 1.0

");}

另一个问题是当打破精确表示的限制时系统的行为。当使用整数算术时,算术运算的结果大于该类型的范围时,可以用多种方法检测到该结果:处理器标志寄存器中的特殊OVERFLOW位被翻转,并且结果与预期的显着不同。

如上例所示,在浮点运算中,精度的下降是无声的。

希望这有助于理解为什么在C语言中需要许多基本数字类型。

假设字母代表0/1。然后,浮点数看起来(从原理上)类似于:

smmmmee

其中s是符号+/-,数字是.mmmm x 10 ^ ee

现在,如果您有两个紧随其后的数字:

.mmm0 x 10 ^ ee

.mmm1 x 10 ^ ee

那么对于大指数ee,其差异可能大于1。

当然,以2为底的数字不能精确表示为1 / 5、0.2。分数求和将增加误差。

(请注意,这不是确切的表示形式。)

我认为您的尾数和指数翻转了,应该是SEEMMMM

@GeorgeMitchell是的; 我几乎用了真实的顺序。 我以易于阅读的顺序保存它。 如果对位表示感兴趣,则需要更多(位数量,NaN,数字边界); 该引用足够可读。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值