我想知道为什么该std::put_money()
函数接受美分而不是美元。还要查看 cppreference 上的定义,它并没有说明输入数字应该是什么。
无论使用哪种货币,我们都必须使用该货币的可能最低十进制值的十进制数,这是真的吗?(即,如此* 1.0
,* 100.0
或* 1000.0
视情况而定?)因为这似乎包含了与当前语言环境相反的货币知识......
我想知道为什么该std::put_money()
函数接受美分而不是美元。还要查看 cppreference 上的定义,它并没有说明输入数字应该是什么。
无论使用哪种货币,我们都必须使用该货币的可能最低十进制值的十进制数,这是真的吗?(即,如此* 1.0
,* 100.0
或* 1000.0
视情况而定?)因为这似乎包含了与当前语言环境相反的货币知识......
一般的想法是您不想将浮点数与货币一起使用,因为具有有限十进制数字的值可以在二进制中是周期性的,并且鉴于浮点值具有有限的精度,这会在对它们求和时导致意外;通常的例子是
#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
。
处理该问题的一种简单方法是使用整数值表示“货币的最小非小数单位”(感谢@Justin 的报价);这确保了当用户输入 $ 0.10 时,它被精确表示,并且不会导致任何舍入意外,至少只要我们正在处理期望精确精度的值。
这很好并解释了美分,但为什么long double
而不是一些整数类型?我在这里推测,但我看到两个合理的动机:
但最重要的是,历史上浮点值在各种平台上都具有最佳精度,即使对于整数值也是如此。long long
(保证至少为 64 位)是最近添加到标准中的,long
通常为 32 位宽:它将货币价值限制在 2100 万美元左右。
OTOH,即使是double
大多数平台上的平原也有 53 位尾数,这意味着它可以精确地表示高达 9007199254740991 的整数值 - 所以,大约是 9 亿美元;这足以准确地代表美国公共债务(低至美分),因此对于几乎其他任何事情来说,它可能已经足够精确了。他们可能选择了 “他们可以解决问题的最大锤子”(即使现在它通常和平原一样大)。long
double
double
因为这似乎包含了与当前语言环境相反的货币知识......
是与否;我认为这个想法是,只要您使用相关的语言环境方面进行输入和输出,您根本不应该真正关心 - 库应该为您进行转换,您只需使用精确大小的数字对你来说应该不重要。
这就是理论;但正如评论中所说,C 和 C++ 语言环境是一款设计糟糕的软件,设计过于复杂,但在实际使用测试时却不尽如人意。
老实说,我永远不会“真正”使用这些东西: