c++ - 为什么 std::put_money() 需要分钱?

标签 c++ locale money-format

我想知道为什么 std::put_money() 函数接受美分而不是美元。还有 looking at the definition on cppreference , 它没有说明输入数字应该是什么。

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

最佳答案

一般的想法是您不想对货币使用 float ,因为小数位数有限的值在二进制中可能是周期性的,并且鉴于浮点值具有有限的精度,这会在求和时导致意外他们;通常的例子是

#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 位宽:它会将货币值(value)限制在微不足道的范围内~2100 万美元。

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

Because that seems to incorporate knowledge of the currency opposed to the current locale...

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


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

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

  • 你永远无法确定标准库更新了多少,它有多破(我曾经让 VC++ 无法进行意大利本地化数字的往返),如果它真的支持你关心的货币。
  • 确实需要关心它的“货币的最小非分数单位”的概念是什么,如果您需要以图书馆期望的格式与文本 IO 之外的任何东西交谈 - 比如说,您必须从网络服务获取股票价格,或者如果您有内置数据与用户输入相结合;
  • 同样适用于机器可读格式的序列化;在存储用户数据时,您不想让自己暴露在变幻莫测的 C 运行时和操作系统配置中,尤其是当它们要与其他应用程序交换时,尤其是当所述应用程序运行在不同的 C 运行时(它甚至可能是为不同的操作系统编译的您自己的应用程序!)或不同的语言。

关于c++ - 为什么 std::put_money() 需要分钱?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50475178/

相关文章:

c++ - 如何应用样条基矩阵?

c++ - 跨平台区域设置表

PHP 间隔与下限

c++ - 两个8位数组协方差的快速实现

c++ - 具有非指针/引用返回类型的协变返回类型

perl - Locale::Maketext::Simple 的警告消息

c# - Thread.CurrentThread.CurrentCulture 在线程池内的线程中不工作

php - 如果处理 float 的钱很糟糕,那么为什么 money_format() 会这样做呢?

带空格的 PHP 货币格式

c++ - Boost mpi x64 警告 "size_t to int"