(楼层)如何在C中工作?当乘以100并调用(floor)时var = 4.2的奇怪结果

问题描述 投票:-5回答:3

(楼层)如何在C中实际工作?据techonthenet说。 com,

在C编程语言中,floor函数返回小于或等于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

c integer cs50 floor
3个回答
2
投票

这与不精确有关吗?

它与不精确有关。

您不能用有限的位数表示无限数量的浮点值,因此实际存储在浮点类型中的是大多数值的近似值。 4.2无法用32位float类型完全表示;实际存储的是更接近4.199999809的东西。 你需要48位有效数字来表示它,这意味着你需要使用64位double

=叹气=我无法添加。 double让你更接近4.2,但不完全正确。

这只是谈论存储,而不是算术运算中的舍入和错误传播。

一般来说,最好使用double而不是float进行浮点工作(更大的范围和精度)。此外,最好将货币金额存储在整数类型中,缩放到最小单位(例如,而不是存储4.2美元,存储420美分或4200密尔)。您仍然需要使用浮点类型来计算兴趣和类似的东西,但是您需要在执行适当的舍入和缩放后将这些结果存储回整数类型。


1
投票

float/double不能完全代表所有可能的数字。典型的float可以代表大约232个不同的数字。 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*100a*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

当数字需要四舍五入到最接近的0.01时,使用floor()将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

金钱在C中有许多特殊问题,各种方法都有weaknesses。使用float是一个非常弱的选择。


0
投票

在尝试降低值之前,打印美元的值以查看实际存储的内容。

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