1

我正在编写一个程序,该程序从输入中获取美元金额并以文字形式显示金额。此时无法使用字符串、数组或函数,所以我用 switch 结构解决了它,尽管它不是很有效。

但是,当我将输入从浮点数转换为整数并尝试使用模数找出小数点后的数字时,我的问题就出现了;由于某种原因,它没有返回正确的数字。

所以说 321.78 提取第一个小数(或 8)它返回一个 7。我不太确定为什么会发生这种情况,以及如何修复它。

这是我第一部分的代码

float number;
int digit1, digit2, digit3, decimals, decimal1, decimal2, int_number;

cout << "Enter a dollar amount from 0-1000: ";
cin >> number;

int_number = number * 100;

digit1 = (int_number % 1000)/100; //ones
digit2 = (int_number % 10000)/1000; //tens
digit3 = (int_number % 100000)/10000; // hundreds

decimal1 = int_number % 10;
decimal2 = (int_number % 100)/10;

如果输入为 321.78,则 decimal1 应返回 8。我错过了什么吗?任何帮助,将不胜感激。

4

6 回答 6

4

首先,请收藏每个计算机科学家应该知道的关于浮点运算的知识

你的问题是浮点精度。试试下面的简单例子:

#include <iostream>

int main()
{
    float f;
    std::cin >> f;
    int x = f * 100;
    std::cout << x;
}

你会看到它x有价值32177。这是因为浮点类型只有一定的精度。321.78与a最接近的float可表示值是321.779998779296875。如您所见,这略小于321.78. 当你将它乘以 100 时,你得到的东西比32178转换为inthas value时的值要少一些32177

这里的问题实际上是您正在向用户询问一个float值。由于您直接提取到 afloat中,因此您对用户施加了限制,即他们只能输入可由float. 显然这是非常愚蠢的,因为您最终只会将该值转换为int. 想象一下自动取款机做到了这一点!会有很多丢失的便士。相反,这里的正确方法是将输入作为字符串读取并解析为适当的int值。

于 2013-04-18T12:29:43.050 回答
1

这是我的答案,基于 sftrabbit 的评论:

#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

int main(){

  string str1;
  cout << "enter number:";
  cin  >> str1;

  //READ AS A STRING AND REMOVE '.'

  str1.erase(std::remove(str1.begin(), str1.end(), '.'), str1.end());

  //CAST STRING TO VALUE
  int value = atoi(str1.c_str());

  //LOOP THROUGH THE PROCESS YOUR WERE DOING BEFORE
  int divisor = 10;
  int  counter = 1;
  while(divisor < 10*value){

    cout << "Digit " << counter << " = " << value%divisor/(divisor/10) << endl;
    divisor *=10;
    counter++;
  }

  return 0;
}
于 2013-04-18T12:42:48.973 回答
1

任何精度有限的浮点类型都容易出现舍入错误(谷歌一下,你会得到关于这些问题的大量信息)。

有一些半生不熟的解决方案floor (number * 100 + 0.5),但在特殊情况下仍然存在舍入错误和/或可能在不同平台上给出不同的结果。

对于小数点有限的货币,我不会费心使用浮点数并弄乱它们 - 只需将输入读取为字符串并首先正确解析它,省略与浮点数/双精度数及其问题相关的任何内容。它们只是不适合这项工作的数据类型。

于 2013-04-18T12:34:03.100 回答
0

要逐个提取数字,您可以这样做: int_number = number * 100;

hundreds = int_number / 10000;
tens = (int_number - hundreds*10000) / 1000;
ones = (int_number - hundreds*10000 - tens * 1000) / 100
decimal1= (int_number - hundreds*10000 - tens * 1000 - ones * 100) / 10;
decimal2= int_number - hundreds*10000 - tens * 1000 - ones * 100 - decimal1 * 10;
于 2013-04-18T12:23:56.803 回答
0

321.78 不能在浮点域中精确表示。你的演员表

int_number = number * 100;

只是删除最后一位数字并且不执行四舍五入。尝试

int_number = static_cast<int> (floor (number * 100 + 0.5f))

反而。

于 2013-04-18T12:28:32.700 回答
0

这就像将 1.5 转换为整数一样:结果类型没有足够的精度来准确地表示原始值。与 321.78 相同:浮点值不能准确表示该值,最终得到的值比您预期的略小,即 321.77#### 其中 #### 表示额外的十进制数字太繁琐在这里计算。当该值乘以 100 并转换为 int 时,它会被截断,并且 32177.#### 变为 32177。

编辑:忘了提及解决方案。

int dollars;
int cents;
char dp;
std::cin >> dollars;
std::cin >> dp;
std::cin >> cents;
cents += dollars * 100;

错误检查留给读者作为练习。

于 2013-04-18T12:32:20.677 回答