4

我想知道为什么该std::put_money()函数接受美分而不是美元。还要查看 cppreference 上的定义,它并没有说明输入数字应该是什么。

无论使用哪种货币,我们都必须使用该货币的可能最低十进制值的十进制数,这是真的吗?(即,如此* 1.0* 100.0* 1000.0视情况而定?)因为这似乎包含了与当前语言环境相反的货币知识......

4

1 回答 1

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


处理该问题的一种简单方法是使用整数值表示“货币的最小非小数单位”(感谢@Justin 的报价);这确保了当用户输入 $ 0.10 时,它被精确表示,并且不会导致任何舍入意外,至少只要我们正在处理期望精确精度的值。

这很好并解释了美分,但为什么long double而不是一些整数类型?我在这里推测,但我看到两个合理的动机:

  • 少量货币是存在的,通常是单一价格(例如每升汽油的价格);精度通常不是问题——无论如何你都要将它乘以另一个浮点值——但你希望能够读取这些值;
  • 但最重要的是,历史上浮点值在各种平台上都具有最佳精度,即使对于整数值也是如此。long long(保证至少为 64 位)是最近添加到标准中的,long通常为 32 位宽:它将货币价值限制在 2100 万美元左右。

    OTOH,即使是double大多数平台上的平原也有 53 位尾数,这意味着它可以精确地表示高达 9007199254740991 的整数值 - 所以,大约是 9 亿美元;这足以准确地代表美国公共债务(低至美分),因此对于几乎其他任何事情来说,它可能已经足够精确了。他们可能选择了 “他们可以解决问题的最大锤子”(即使现在它通常和平原一样大)。long doubledouble

因为这似乎包含了与当前语言环境相反的货币知识......

是与否;我认为这个想法是,只要您使用相关的语言环境方面进行输入和输出,您根本不应该真正关心 - 库应该为您进行转换,您只需使用精确大小的数字对你来说应该不重要。


这就是理论;但正如评论中所说,C 和 C++ 语言环境是一款设计糟糕的软件,设计过于复杂,但在实际使用测试时却不尽如人意。

老实说,我永远不会“真正”使用这些东西:

  • 如果它真的支持你关心的货币,你永远无法确定标准库的更新程度,它的损坏程度(我曾经让 VC++ 无法执行意大利本地化数字的往返)。
  • 如果您需要以图书馆期望的格式与文本 IO 以外的任何内容进行交谈,您确实需要关心它的“货币的最小非小数单位”的概念是什么 - 例如,您必须获得股票的价格来自网络服务,或者如果您有内置数据与用户输入相结合;
  • 以机器可读格式进行序列化也是如此;在存储用户数据时,您不想让自己暴露于 C 运行时和操作系统配置的变幻莫测,特别是如果它们要与其他应用程序交换,特别是如果所述应用程序在不同的 C 运行时上运行(它甚至可能是为不同的操作系统编译的您自己的应用程序!)或不同的语言。
于 2018-05-22T21:05:57.833 回答