Почему центы для std :: put_money ()? - PullRequest
0 голосов
/ 22 мая 2018

Мне интересно, почему функция std::put_money() принимает центы вместо долларов.Также , глядя на определение cppreference , он не говорит, каким должно быть входное число.

Верно ли, что в любой валюте мы должны использовать десятичное число с минимально возможным десятичным числомстоимость указанной валюты?(то есть * 1.0, * 100.0 или * 1000.0 в зависимости от обстоятельств?) Потому что это, кажется, включает знание валюты, противоположной текущей локали ...

1 Ответ

0 голосов
/ 23 мая 2018

Общая идея заключается в том, что вы не хотите использовать плавающую точку с валютой, потому что значения с конечным числом десятичных цифр могут быть периодическими в двоичном формате, а учитывая, что значения с плавающей точкой имеют конечную точность, это приводит к неожиданностям при суммированииих;обычный пример -

#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 бита: его денежные значения будут ограничены до скудных ~ 21 миллиона долларов.

    OTOH, даже обычный double на большинстве платформ имеет 53-значную мантиссу, что означает, что он может представлять в точности целые значения вплоть до 9007199254740991 - так, что-то вроде 90 тысяч миллиардов долларов;этого достаточно, чтобы точно представить государственный долг США в центах, так что, вероятно, достаточно точно для всего остального.Вероятно, они выбрали long double как «самый большой молот, который они могут бросить в задачу» (даже если в настоящее время он обычно такой же большой, как равнина double).

Потому что это, кажется, включает в себя знание валюты, противоположной текущей локали ...

Да и нет;Я думаю, что идея состояла в том, что, пока вы используете соответствующие фасеты локали как для ввода, так и для вывода, вам просто не нужно заботиться - библиотека должна делать преобразования за вас, и вы просто работаете с числами, точная величина которыхне должно иметь большого значения для вас.


Это теория;но, как сказано в комментариях, локали C и C ++ являются плохо разработанным программным обеспечением с чрезмерно сложным дизайном, который, тем не менее, не подходит для тестирования в реальных условиях.

Честно говоря, я бы никогда не использовал этот материал«по-настоящему»:

  • вы никогда не можете быть уверены в том, насколько обновлена ​​стандартная библиотека, насколько она сломана (у меня когда-то был VC ++, когда я не мог выполнить обход италически локализованных чисел),если он на самом деле поддерживает валюты, которые вас интересуют.
  • вам нужно нужно позаботиться о том, каково его понятие «наименьшей нефракционной единицы валюты», если вам нужно говорить с чем-либокроме текстового ввода-вывода в формате, ожидаемом библиотекой - скажем, вы должны получить цену акции из веб-службы или если у вас есть встроенные данные для объединения с пользовательским вводом;
  • то же самое длясериализация в машиночитаемом формате;Вы не хотите подвергать себя капризам своей среды выполнения C и конфигурации ОС при хранении пользовательских данных, особенно если они должны обмениваться с другими приложениями, особенно если указанные приложения работают в другой среде выполнения C (это может дажебыть вашим собственным приложением, скомпилированным для другой операционной системы!) или другого языка.
...