int转换 - 给我奇怪的数字

时间:2013-08-06 07:41:34

标签: c++

我是编程世界的新手,C ++已经失去了我。我的程序中有这些行

pennies=(amount-nickels*.05)/.01;

金额double,而镍币int

便士double时,程序会返回正确的值,但只要便士,事情就会稍微偏离(大部分时间为1) int

为什么会这样?

4 个答案:

答案 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.10.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,因此计算结果发生在只有双重格式。