(楼层)如何在C中实际运作? 据techonthenet说。 com,
在C编程语言中,floor函数返回最大值 小于或等于x的整数(即:舍入为x 最接近的整数)。
将值4.2输入get_float()后, 我使用floor(4.2 * 100),将它们变成美分并删除小数位并将其变成整数。
但是,我很困惑为什么专门输入值4.2会为楼层(4.2 * 100)和楼层(4.2 * 1000/10)返回不同的值? 这与不精确有关吗?
见图片: When variable entered as 4.2, floor produces different values
顺便说一下,我刚刚开始使用edx上的CS50,并且尝试了第1周课程的最后一次练习..也会喜欢对代码其他部分的任何评论。 有关此问题的更多信息: http://docs.cs50.net/problems/greedy/greedy.html
答案 0 :(得分:2)
这与不精确有关吗?
它与不精确有关。
您不能用有限的位数表示无限数量的浮点值,因此实际存储在浮点类型中的是大多数值的近似值。 4.2
无法在32位float
类型中以完全表示;实际存储的内容更接近4.199999809
。 你需要48位有效数字来表示它,这意味着你需要使用64位 double
。
= sigh = 我无法添加。 double
让你更接近4.2,但不完全正确。
这只是谈论存储,而不是关于算术运算中的舍入和错误传播。
通常,使用double
代替float
进行浮点工作(更大范围的和精度)会更好。此外,最好将货币金额存储在整数类型中,并缩放到最小单位(例如,而不是存储4.2
美元,存储420
美分或4200
密耳)。您仍然需要使用浮点类型来计算兴趣和类似的东西,但是在进行适当的舍入和缩放之后,您希望将这些结果存储回整数类型。
答案 1 :(得分:1)
float/double
无法准确表示所有可能的数字。典型的float
可代表约2 32 不同的数字。 4.2不是其中之一。而是使用最近的值。打印using FLT_DECIMAL_DIG
以查看数字的足够精确度,以确定它不完全是4.2
#include <float.h>
float a = 4.2f;
printf("%.*e\n", FLT_DECIMAL_DIG-1, a);
// 4.19999981e+08
a *= 100;
printf("%.*e\n", FLT_DECIMAL_DIG-1, a);
// 4.19999969e+02
a = floor(a);
printf("%.*e\n", FLT_DECIMAL_DIG-1, a);
// 4.19000000e+02
使用a*100
和a*1000
产品会产生四舍五入到最接近的可回答的答案并回想起来,a
不是完全 4.2。
a = 4.2;
printf("%.*e\n", FLT_DECIMAL_DIG-1, a * 100); // 4.19999969e+02
printf("%f\n", floor(a * 100)); // 419.000000
printf("%.*e\n", FLT_DECIMAL_DIG-1, a * 1000); // 4.20000000e+03
printf("%.*e\n", FLT_DECIMAL_DIG-1, a * 1000/10); // 4.20000000e+02
printf("%f\n", floor(a * 1000 / 10)); // 420.000000
使用floor()
是一个不好的选择,当需要将数字四舍五入到最接近的0.01时,将4.2分成整数和分数。相反,使用匹配类型函数进行缩放,舍入然后分离。
float a100 = a*100;
printf("%.*e\n", FLT_DECIMAL_DIG-1, a100); // 4.19999969e+02
a100 = roundf(a100);
printf("%.*e\n", FLT_DECIMAL_DIG-1, a100); // 4.20000000e+02
float a100th = fmodf(a100, 100);
printf("%.*e\n", FLT_DECIMAL_DIG-1, a100th); // 2.00000000e+01
a = (a100 - a100th)/100;
printf("%.*e\n", FLT_DECIMAL_DIG-1, a); // 4.00000000e+00
Money 在C中有许多特殊问题,各种方法都有weaknesses。使用float
是一个非常弱的选择。
答案 2 :(得分:0)
打印美元的价值,以便在尝试降低价值之前查看实际存储的内容。