如果float有6位精度,为什么我们可以用printf显示6位以上的float?

问题描述 投票:0回答:3

让我们考虑以下代码:

#include <stdio.h>
int main()
{
    float x = 0.33;
    printf("%.100f",x);

    return 0;
}

如果 float 有 6 位精度,如何用

printf
显示超过 6 位?

c floating-point precision
3个回答
3
投票

您尝试将小数 0.33 转换为

float
。但是,与大多数小数一样,数字 0.33 无法在类型
float
内部使用的二进制表示中精确表示。您可以获得的最接近的是二进制分数
0.0101010001111010111000011
。这个分数,如果我们把它转换回十进制,正好是 0.3300000131130218505859375.

在十进制中,如果我告诉你你有 7 位有效数字,你尝试表示数字 1/3 = 0.333…,你期望得到 0.333333300000。也就是说,您希望获得一些与原始数字相匹配的有效数字,然后在没有足够意义的地方加上 0。二进制分数的工作方式相同:对于类型

float
,二进制分数总是恰好有 24 位有效位,后跟(如果你愿意的话)任意数量的二进制 0。

当我们将该二进制数转换回十进制时,我们得到大约 7 位数字与我们认为的十进制数相匹配,后面不是零,而是看起来像随机数字的数字。例如,二进制

float
的 1/3 是
0.0101010101010101010101011000000000
(注意 24 位有效位),转换为十进制时是 0.333333343267440795898437500000(注意 7 位精确数字)。

当您听到类型

float
具有大约 7 位有效数字时,这确实 not 意味着您将获得原始数字的 7 位,后跟 0。这意味着你会得到 approximately 原始号码的 7 位数字(但可能是 6 位,或者可能是 8 位或 9 位或更多),然后是一些可能与您的原始号码不匹配但不匹配的数字全0,要么。但这实际上不是问题,特别是如果(按照推荐和适当的方式)将此数字四舍五入到有用的数字。这可能是一个问题(虽然这经常出现)是当你用无用的数字打印回数字时,格式如
%.100f
,你会看到一些看起来很奇怪的数字全部为 0,这让你感到困惑,就像这里一样。

类型

float
double
在内部使用二进制表示的事实会导致像这样的无尽惊喜。用二进制表示并不奇怪(我们都知道计算机用二进制做所有事情),但是二进制fractions无法准确表示我们习惯的小数,这真是令人惊讶。请参阅规范的 SO 问题浮点数学是否损坏?了解更多信息。


0
投票

如果float有6位精度,为什么我们可以用

printf
显示6位以上的float?

A

float
每个定义都没有 6 位精度。您已选择显示比实现可能提供的更多的数字 - 它提供了。

为什么我们可以用

printf
显示6位以上的浮点数?

您可以告诉程序显示您在

float
/
double
/
long double
中的任何内容,它仍然是一个近似值。

显示这样一个变量的当前内容最好在调试时完成。

比较:https://en.wikipedia.org/wiki/IEEE_754


0
投票

“如果浮点数有 6 位精度……”--> 是一个弱前提。

普通

float'
没有6位的十进制精度,而是24位的二进制精度。


怎么可能用

printf
(?)

显示超过6位数字

当以十进制形式打印二进制浮点数时,每个二进制数字都会贡献一些 2 的幂,例如 ..., 16, 8, 4, 2, 1, 0.5, 0.25, 0.125, 0.0625, ...

这些 2 的幂的总和很容易超过 6 位小数。

在极端情况下,

FLT_TRUE_MIN
通常具有以下精确值:

0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125

很少有 9 位有效的小数位更重要。

© www.soinside.com 2019 - 2024. All rights reserved.