2013-04-18 40 views
1

我正在写一个程序,它从输入中获取一美元的金额,并以单词形式显示金额。此时无法使用字符串,数组或函数,所以我使用开关结构解决了这个问题,尽管它效率不高。整数模数

但是,我的问题来了,当我已经将输入从一个浮点数转换为整数,并尝试使用模数单数出小数点后的数字;由于某种原因,它不会返回正确的数字。

所以说为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; 

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

+1

尝试打印'int_number'。 –

+0

我也怀疑这是一个精确问题。更好地利用'double'比'float' – syam

+2

如果你希望用户输入'321.78'但它作为'int'值'32178',我建议不要经历一个'float'到那里。真的,你想以字符串的形式读取它,解析它以除去'.'并检查格式错误,然后将字符串'32178'转换为'int'。以'float'作为输入基本上告诉用户他们必须输入一个可表示的浮点值。 –

回答

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; 

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

+0

感谢堆,我不知道发生了什么。感谢您解释它! – KingKong

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; 
+0

这不会帮助解决浮点精度问题 –

+0

我不认为在逗号后有一个2位数的值存在精确浮动问题 – Nagasaki

+0

我可以向你保证。 10位数的2位数字可以是2位数的无限期循环。321.78是321.7799987792968750 ...作为浮点数和321.7799999999999727 ...作为双精度数。 –

0

321.78不能在float域中精确表示。您的演员表

int_number = number * 100; 

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

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

改为。

+0

所以它是一个精确的问题,因为我的表情没有正确地将数字舍去? 你能否帮助解释为什么+0.5? – KingKong

+0

看到sftrabbit的帖子。 – eel76

+0

@KingKong 0.5技巧可能会经常使用,但不是在任何情况下。仍然会有一些情况你是一位数字。简单地不要使用浮点来进行定点计算。 –

4

首先请书签What Every Computer Scientist Should Know About Floating-Point Arithmetic

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

#include <iostream> 

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

你会看到x具有价值32177。这是因为浮点类型只有一定的精度。 float可以具有的321.78的最接近的可表示值是321.779998779296875。如您所见,这略低于321.78。当你乘以100时,你有一些小于32178的东西,当它转换为int时,其值为32177

这里的问题实际上是您要求用户输入float的值。由于您直接提取到float,因此您要限制用户只能输入可由float表示的值。显然这很愚蠢,因为你只能将该值转换为int。想象一下ATM做到了!会有许多丢失的便士。相反,这里的正确方法是将输入作为字符串读取,并解析为适当的int值。

+0

很好解释它哈哈。谢谢你的帮助。 – KingKong

1

的精度限制的任何浮点类型很容易出现舍入误差(google了一下,你会得到的信息吨关于这些问题)。

有喜欢floor (number * 100 + 0.5)半生不熟的解决方案,但这些仍然舍入误差遭受特殊情况和/或可以给不同平台上的不同的结果。

在小数位数有限的情况下,我不会打扰使用浮点数并且弄乱它们 - 只是将输入读为字符串,并且首先正确地解析它,省略与float/double有关的任何事情,他们的问题。他们不是这份工作的正确数据类型。

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; 
}