c++ - double,float,{0.0},{0.0f},有什么大不了的?

标签 c++ floating-point double

所以我写了这个小练习程序,告诉您所需数量的镍和美分。我不理解为什么即使数学是正确的,程序也会输出0美分。我无法理解问题所在。

// Example program
#include <iostream>

using namespace std;

int main()
{
    const double nickels{0.05};
    const double cents{0.01};
    int amt_needed_nickels{0}, amt_needed_cents{0};
    double amt_val{0.06f}; // for 0.06 cents
    double amt_val_copy{amt_val};
    
    amt_needed_nickels = amt_val / nickels;
    if(amt_needed_nickels != 0)
        amt_val -= (nickels * amt_needed_nickels);
    amt_needed_cents =  amt_val / cents;
    
    cout << "If it costs $" << amt_val_copy << ", you'll need:\nNickels: " << amt_needed_nickels << "\nCents: " << amt_needed_cents << "\n";
    cout << "Even though amt_val is " << amt_val << ", and cents is also " << cents << ", and 0.01/0.01 does equal 1, why is amt_needed_cents not 1?\n";
}

公平地说,我知道我是否将const double cents {0.01}更改为const float cents {0.01},并从double amt_val {0.06f}中删除f;加倍amt_val {0.06};它会起作用,但是我无法理解表面下到底发生了什么。为什么程序在上面的amt_needed_cents中给出0,而在其他情况下给出1?
// Example program
#include <iostream>

using namespace std;

int main()
{
    const double nickels{0.05};
    const float cents{0.01};
    int amt_needed_nickels{0}, amt_needed_cents{0};
    double amt_val{0.06}; // for 0.06 cents
    double amt_val_copy{amt_val};
    
    amt_needed_nickels = amt_val / nickels;
    if(amt_needed_nickels != 0)
        amt_val -= (nickels * amt_needed_nickels);
    amt_needed_cents =  amt_val / cents;
    
    cout << "If it costs $" << amt_val_copy << ", you'll need:\nNickels: " << amt_needed_nickels << "\nCents: " << amt_needed_cents << "\n";
    cout << "I know this is correct, but I don't know what the compiler is thinking with this as compared to the other\n\n";
}


最佳答案

浮点计算并不精确,在进行数学运算时会得到很小的差异,如果您尝试检查数字的精确相等性,则会破坏程序。例如,1.2 * 3并不完全是3.6(请注意,这并不意味着所有计算都是不精确的:例如,乘以2的任何幂总是正确的:诸如1.5 * 21.1 / 4之类的东西总能给出最佳答案)。这是因为像1/101/100这样的十进制分数不能精确地用二进制表示,这在我们的硬币基于1/100(美分)的情况下是一个问题。
在您的程序中,您应该通过将所有值转换为美分来将硬币表示为整数,然后一切正常。也就是说,您知道您将要处理的最大分母是100,因此您最好将所有内容乘以100。因此,nickels将是5cents将是1,所有计算都将是精确的。
为避免混淆,这是整数代码:

int dollars = 100, nickels = 5, cents = 1;

int amt_needed_dollars = amt_val / dollars;
amt_val -= amt_needed_dollars * dollars;
int amt_needed_nickels = amt_val / nickels;
amt_val -= amt_needed_nickels * nickels;
// skipped dividing by cents, because it's '1' anyway
int amt_needed_cents = amt_val;

关于c++ - double,float,{0.0},{0.0f},有什么大不了的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62826117/

相关文章:

c - 如何获得 10 次方的 double 的尾数和指数?

c++ - 如何在 UnrealEngine 中对非 2 的幂纹理进行下采样?

c++ - 谁能帮助我理解此C++代码?

c++ - 更改 Windows DLL 加载顺序? (加载顺序,不是搜索顺序)

c++ - 构建 vcxproj 文件给我一个无信息错误 "The system cannot find the path specified"

c - 在 C 中将字节数组转换为 float/long 的问题

c++ - 可以使用一个指针来匹配 Python 中 float 变量的 int 值吗?

Code::Blocks 无法识别简单 C 程序中的双重标识符 (%lf)

java - 这是根据规范进行的 Java 双重解析行为吗?

java - java中的 double 超出范围