C++ while 循环中的浮点精度
C++ floating point accuracy in while loops
我试图通过使用一系列while循环来计算美元和硬币面额的总数。然而,当我下到硬币时,我差了一分钱。当我输入 99.95 时,我得到 3 个季度的输出,1 角钱、1 镍币和 4 便士。我已将问题缩小到浮点精度问题。但是,我研究的所有解决方案都不适用于我的情况。有什么指示吗?
#include <iostream>
using namespace std;
int main()
{
float amount;
cout<<"enter amount" << endl;
cin>>amount;
int pennies=0, nickels=0, dimes=0, quarters=0, ones=0, fives=0,
tens=0,
twenties=0, fifties=0, hundreds=0;
while (amount >= 100)
{
hundreds = hundreds +1;
amount = amount - 100;
}
while (amount >= 50)
{
fifties = fifties +1;
amount = amount - 50;
}
while (amount >= 20)
{
twenties = twenties +1;
amount = amount - 20;
}
while (amount >= 10)
{
tens = tens +1;
amount = amount - 10;
}
while (amount >= 5)
{
fives = fives +1;
amount = amount - 5;
}
while (amount >= 1)
{
ones = ones +1;
amount = amount - 1;
}
while (amount >= .25)
{
quarters = quarters +1;
amount = amount - .25;
}
while (amount >= .10)
{
dimes = dimes +1;
amount = amount - .10;
}
while (amount >= .05)
{
nickels = nickels +1;
amount = amount - .05;
}
while (amount >= .01)
{
pennies = pennies +1;
amount = amount - .01;
}
cout<<endl<<"pennies:"<< pennies;
cout<<endl<<"nickels:"<<nickels;
cout<<endl<<"dimes:"<<dimes;
cout<<endl<<"quarters:"<<quarters;
cout<<endl<<"ones:"<<ones;
cout<<endl<<"fives:"<<fives;
cout<<endl<<"tens:"<<tens;
cout<<endl<<"twenties:"<<twenties;
cout<<endl<<"fifties:"<<fifties;
cout<<endl<<"hundreds:"<<hundreds<<endl;
return 0;
}
在需要精确值的情况下不要使用浮点数。 99.95 不能用浮点数或双精度数精确表示,有点像 1/3 不能使用有限数量的正常十进制数字精确表示。
正如Doug T.所建议的那样,你可以使用整数来保存便士的数量。当用户键入 123.45 时,将其读取为两个整数,然后将其存储为 12345 便士,而不是 123.45 美元。
在这种情况下,您还可以尝试将上次while (amount >= .01)
更改为类似 while (amount >= .005)
.这不是一个通常可以推荐的解决方案,如果这是一个现实生活中的银行应用程序,你真的应该避免它,但它至少有助于防止一些错误。
在这种情况下,您应该使用定点值,而不是浮点值。
虽然人们用美元来看待货币,这并不准确,但金钱是以美分来衡量的,这是准确的。只需数美分数,除以 100 得到美元金额,取模数得到美分金额。在这种情况下,浮点不是正确的工具。
通常,二进制浮点数不能表示小数十进制值,即使小数总数很小也是如此。例如,0.1
无法准确表示。
为了处理精确值,存在不同的方法,这些方法都相当于使用与2
不同的基数。根据具体需求,这些方法或多或少涉及。对于您的情况,最简单的方法是使用固定精度而不是可变精度。要以固定精度计算,您只需使用一个整数,该整数表示您实际想要的值乘以合适的 10
次方。根据您执行的计算量,您可以将逻辑打包到一个类中,也可以将其分布在整个代码中。在一个"真正的"应用程序中,我会把它打包到一个班级,一个作业中(家庭作业,面试等)。我可能只是将逻辑直接应用于int
。
这是固定代码,我使用了TJD的建议,而不是使用.01,而是使用了.0099。对于我的问题似乎有效,谢谢大家!
#include <iostream>
using namespace std;
int main()
{
float amount;
cout<<"enter amount" << endl;
cin>>amount;
int pennies=0, nickels=0, dimes=0, quarters=0, ones=0, fives=0,
tens=0,
twenties=0, fifties=0, hundreds=0;
float p = .0099, n = .0499, d = .099, q = .2499;
while (amount >= 100)
{
hundreds = hundreds +1;
amount = amount - 100;
}
while (amount >= 50)
{
fifties = fifties +1;
amount = amount - 50;
}
while (amount >= 20)
{
twenties = twenties +1;
amount = amount - 20;
}
while (amount >= 10)
{
tens = tens +1;
amount = amount - 10;
}
while (amount >= 5)
{
fives = fives +1;
amount = amount - 5;
}
while (amount >= 1)
{
ones = ones +1;
amount = amount - 1;
}
while (amount >= q)
{
quarters = quarters +1;
amount = amount - q;
}
while (amount >= d)
{
dimes = dimes +1;
amount = amount - d;
}
while (amount >= n)
{
nickels = nickels +1;
amount = amount - n;
}
while (amount >= p)
{
pennies = pennies +1;
amount = amount - p;
}
cout<<endl<<"pennies:"<< pennies;
cout<<endl<<"nickels:"<<nickels;
cout<<endl<<"dimes:"<<dimes;
cout<<endl<<"quarters:"<<quarters;
cout<<endl<<"ones:"<<ones;
cout<<endl<<"fives:"<<fives;
cout<<endl<<"tens:"<<tens;
cout<<endl<<"twenties:"<<twenties;
cout<<endl<<"fifties:"<<fifties;
cout<<endl<<"hundreds:"<<hundreds<<endl;
return 0;
}
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 正在将csv文件读取为双精度矢量
- while循环中while循环的时间复杂度是多少
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 擦除while循环中迭代的元素
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 如何在C++中的同一函数中使用字符串和双精度
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 为什么我不能在 while 循环中创建线程?
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 如何计算具有指定类型的表达式的相对精度和绝对精度
- C++ while 循环中的浮点精度
- 如何以 0.00001 的精度结束此 while 循环([C++],[泰勒级数])
- 以精度为条件的While循环
- 将字符串转换为双精度值,然后在 While 循环中将其推送到向量