我想知道为什么std::put_money()
函数接受美分而不是美元。同样looking at the definition on cppreference,它没有说输入数字应该是什么。
我们必须在所述货币的最低十进制值处使用十进制数,这是真的吗? (即* 1.0
,* 100.0
或* 1000.0
视情况而定?)因为这似乎包含了与当前语言环境相对的货币的知识...
答案 0 :(得分:3)
一般的想法是你不想使用带货币的浮点数,因为具有有限数字的十进制数字的值可以是二进制的周期性的,并且假设浮点值具有有限的精度,这在求和时会导致意外他们;通常的例子是
#include <stdio.h>
int main(void) {
double v = 0.;
for(int i=0; i<10; ++i) v+=0.1;
printf("%0.18g\n", v-1.0f);
return 0;
}
打印-1.11022302462515654e-16
。
处理问题的一个简单方法是使用"the smallest non-fractional units of the currency"的积分值(感谢@Justin的引用);这可以确保当用户输入0.10美元时,它就是精确表示的,并且不会导致任何舍入意外,至少只要我们处理预期精确精度的值。
这很好,并解释了分数,但为什么long double
而不是某种整体类型?在这里我猜测,但我看到两个合理的动机:
但最重要的是,历史上浮点值在广泛的平台上具有最佳精度,即使对于整数值也是如此。 long long
(保证至少为64位)是标准的最新成员,而long
通常是32位宽:它将货币价值上限限制在2100万美元左右。
double
都有一个53位数的尾数,这意味着它可以代表高达9007199254740991的完全积分值 - 所以,就像9万亿美元;这足以将美国的公共债务精确地表示为美分,因此对于其他任何东西而言,它可能足够精确。他们可能选择 long
double
作为“他们可以解决问题的最大锤子”(即使现在它通常与普通double
一样大)。 因为这似乎包含了与当前语言环境相对的货币的知识......
是和否;我认为这个想法是,只要您使用相关的区域设置方面进行输入和输出,您根本就不应该关心 - 图书馆应该为您进行转换,而您只需使用精确幅度的数字对你来说真的不重要。
这就是理论;但正如评论中所说,C和C ++语言环境是一个设计糟糕的软件,设计过于复杂,但在测试实际使用时却不尽如人意。
老实说,我绝不会将这些东西用于“真实”: