【问题标题】:Why cents for std::put_money()?为什么 std::put_money() 需要美分?
【发布时间】:2023-03-09 18:27:01
【问题描述】:

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

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

【问题讨论】:

  • 这是std::money_put 的文档。 Thisstd::put_money 的文档
  • 好吧,用 (long) double 来表示美元是个坏主意,用它来表示美分通常没问题 - 整数可以用 double 完美表示,而且时间不长double 是表示相当大整数的最佳基本类型(当您的 long 是 32 位并且您没有更大的整数时,53 位尾数不会浪费)。
  • 看起来 C++ 标准库的这一部分在 cppreference 上没有很好的记录。直接查阅标准 (eel.is/c++draft/category.monetary) 可能是个好主意,并用找到的内容更新 cppreference(这是一个 wiki)
  • @Justin:TBH,我并不感到惊讶——C 和 C++ 语言环境是一个破碎的、复杂的混乱,没有达到任何合理的预期,而货币格式可能是它们功能中最没用的;无论系统范围内设置何种货币,我从来没有或编写过一个必须“一般”显示货币价值的程序。

标签: c++ locale money-format


【解决方案1】:

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

#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 万美元左右。

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

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

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


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

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

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

【讨论】:

  • 哦,我知道任何货币数字都只能使用整数。我很难理解为什么大多数人不知道这一点。我对 C++ 会做这样的事情感到非常惊讶。酷。
猜你喜欢
  • 2016-09-07
  • 2012-07-28
  • 1970-01-01
  • 2015-04-16
  • 2018-07-25
  • 2011-03-16
  • 1970-01-01
  • 2012-04-03
  • 2021-10-22
相关资源
最近更新 更多