我是编程世界的新手,C ++已经失去了我。我的程序中有这些行
pennies=(amount-nickels*.05)/.01;
金额是double
,而镍币是int
。
当便士为double
时,程序会返回正确的值,但只要便士,事情就会稍微偏离(大部分时间为1) int
。
为什么会这样?
答案 0 :(得分:8)
这种情况正在发生,因为该值被截断,从而失去了小数精度。
对于整数:
int i;
i = 1.1 //stores 1 in i
i = 1.2 //stores 1 in i
i = 1.3 //stores 1 in i
i = 1.4 //stores 1 in i
i = 1.5 //stores 1 in i
i = 1.6 //stores 1 in i
i = 1.7 //stores 1 in i
i = 1.8 //stores 1 in i
i = 1.9 //stores 1 in i
i = 1.999999 //stores 1 in i
我建议你把你的表达改为:
pennies=amount*100-nickels*5;
答案 1 :(得分:3)
正如其他人所指出的,问题是因为0.1
和
0.05
在机器浮动中没有精确的表示
点。这里最简单的解决方案是简单地围绕
结果,而不是截断:
pennies = round( (amount - nickels * 0.05) / 0.01 );
在这种特殊情况下(您正在处理的地方)的更好解决方案 用硬币)只是到处使用整数,并做 一切都以美分而不是美元计算。这停止了 非常快速地工作(或需要一些非常复杂的编程) 然而:甚至计算增值税或销售税等原因 问题。对于这种情况,有两种可能的解决方案:
继续使用double
,根据需要进行四舍五入。这是
最简单,最通用的解决方案。但请注意
使用它时,对二进制值进行舍入,它可以
在某些情况下,与舍入所得到的不同
十进制值。差异应该足够小
每天使用都无关紧要,但大多数国家都有法律规定
指定如何舍入这些值以及舍入的值
规则始终以十进制指定。这就意味着这一点
在法律要求成立的情况下,不能使用解决方案
(例如计算销售税,公司簿记等)。
使用某种十进制类。有一些可用 在网络上。这将导致执行时间变慢。 (通常情况下,谁在乎。你会得到100分的结果 微秒,而不是10.但也有例外;例如 在进行蒙特卡罗模拟时。)
此外,您必须知道何时涉及大值。对于
你的个人财务,几乎可以肯定是无关紧要的,但是
int
确实有一个最大值,并且有一个点
double
无法再正确表示整数值。
当然,如果这只是一个帮助学习C ++的练习,
只需使用round
或整数,不要太担心
其余部分。
至于你的评论“C ++已经失去了我”:这有 与C ++本身无关。你会遇到完全一样的 (几乎)任何编程语言的问题。
答案 2 :(得分:1)
您在表达式的右侧部分计算浮点数,但之后尝试将双精度值存储在int值中。执行此操作时,小数部分将丢失。
答案 3 :(得分:1)
pennies=(amount-nickels*.05)/.01;
在上面的表达式中,分子和分母算术以双形式出现,因为变量金额(为双精度) - 隐式转换在这里发生。最后,如果便士是双倍,计算结果将存储在便士中,如果它是int,则计算结果的小数部分将丢失。 中间计算将始终以双精度进行,并且它不依赖于便士类型。
示例强>
#include <stdio.h>
int main()
{
int a ;
double c,d=10.55555;
a = c= (d+ 10*.5)/0.5 ;
printf("%f : %d/n",c,a);
return 0;
}
输出结果为:
31.111100:31
这里第一个10被提升为浮点数然后10 * .5将被评估,由于加上一个double值,它将被提升为double,然后分母也转换为double,因为分子是double,因此计算结果发生在只有双重格式。