我需要知道浮点数的小数,这是一个像
一样浮点数的函数float in1 = 2013.45
float in2 = 367.678
并导致
float out1 = 0.45
float out2 = 0.678
我见过内置的nf(),但它返回一个String。实现这一目标最优雅/最方便的方法是什么?
编辑:我试过了
float in = 2013.45;
float out = in-floor(in);
但结果是0.44995117而不是0.45。
答案 0 :(得分:3)
编辑:我试过了
float in = 2013.45; float out = in-floor(in);
但结果是0.44995117而不是0.45。
这可能是正确的。你在这里看到的是loss of precision。
为简单起见,首先让我们假装计算机在基数10(换句话说,十进制数字系统)中工作。
A 32 bit float has 7 correct significant decimal digits. 2013.45在内部表示为2013.450。现在,当您减去整数部分时,4个有效数字变为零:
2013.450
- 2013
----------
.450
换句话说, 4位有效数字丢失,结果最多只能精确到3位有效数字。您需要更多的输入 2013.450数字才能获得更精确的结果。不幸的是,您只能使用32位浮点数限制为7位数,并且您无能为力。
浮点计算接下来会发生的是(组成)零附加到结果,直到我们再次有7位有效数字。它被称为规范化。在基数10,我们意外幸运,因为正确的数字恰好是0(最有可能是你混淆的原因)但是计算机在基数2中工作。这段代码显示了实际计算是如何内部执行,十六进制格式和C:
#include <stdio.h>
int main(int argc, char** argv) {
float x = 2013.45;
float floor_x = 2013;
float y = x - floor_x;
printf(" x = %a\n", x);
printf("floor(x) = %.6a\n", floor_x);
printf(" y = %.6a\n", y);
}
打印:
x = 0x1.f75cccp+10
floor(x) = 0x1.f74000p+10
y = 0x1.ccc000p-2
正如您所看到的,y
通过在后面添加三个0
来重新规范化。但是,基数16中的正确数字应该是c
。我们在基数10中幸运只有完全意外,因为在基数10中附加的零和真实数字会重合。
还有一点需要注意。 打印功能可以组成垃圾数字。计算机在内部工作在基座2,但结果打印在基座10中,因此需要从基座2到基座10的转换。即使您可以打印任意数量的浮点数,也不会使其比内部精度更准确。在C中演示,打印1.1
最多15位数字:
#include <stdio.h>
int main(int argc, char** argv) {
float x = 1.1;
printf("x = %.15f\n", x);
}
此程序打印
x = 1.100000023841858
在我的机器上。由于浮点数有7位有效数字,因此第7位数之后的所有内容都应被视为垃圾。如您所见,它是垃圾。
在您的示例中计算float out = in-floor(in);
并且丢失了7位数中的4位之后,您应该只打印最多3位数的结果,这是您的责任。最多3个有效数字0.44995117 0.450这是你所期待的。
答案 1 :(得分:2)
当然最好只使用out = in % 1;
,这适用于正面或负面in
。
答案 2 :(得分:1)
肯定in
:
out = in - (float) floor(in)
否定in
:
out = in - (float) ceil(in)