Вопрос

Я всегда говорю, что в c # переменная типа double не подходит для денег.Все странные вещи могут случиться.Но, похоже, я не могу привести пример, демонстрирующий некоторые из этих проблем.Кто-нибудь может привести такой пример?

(редактировать;первоначально этот пост был помечен как C#;некоторые ответы относятся к конкретным деталям decimal, что , следовательно , означает System.Decimal).

(правка 2:Я конкретно просил какой-нибудь код на c #, так что я не думаю, что это зависит только от языка)

Это было полезно?

Решение

Очень, очень неподходящий. Используйте десятичную дробь.

double x = 3.65, y = 0.05, z = 3.7;
Console.WriteLine((x + y) == z); // false

(пример со страницы Джона здесь - рекомендуемое чтение ;-p)

Другие советы

Вы получите странные ошибки, эффективно вызванные округлением. Кроме того, сравнение с точными значениями чрезвычайно сложно - вам обычно нужно применить какой-то эпсилон, чтобы проверить, является ли фактическое значение «близким». конкретный.

Вот конкретный пример:

using System;

class Test
{
    static void Main()
    {
        double x = 0.1;
        double y = x + x + x;
        Console.WriteLine(y == 0.3); // Prints False
    }
}

Да, это не подходит.

Если я правильно помню, double содержит около 17 значащих чисел, поэтому обычно ошибки округления происходят далеко за десятичной запятой.Большинство финансовых программ использует 4 знака после запятой, что оставляет 13 знаков после запятой для работы, поэтому максимальное число, с которым вы можете работать для отдельных операций, все еще намного превышает государственный долг США.Но ошибки округления будут накапливаться с течением времени.Если ваше программное обеспечение работает в течение длительного времени, вы в конечном итоге начнете терять центы.Некоторые операции могут усугубить ситуацию.Например, добавление больших количеств к небольшим приведет к значительной потере точности.

Вам нужны типы данных с фиксированной запятой для денежных операций, большинство людей не возражают, если вы теряете цент то тут, то там, но бухгалтеры не такие, как большинство людей..

Редактировать
Согласно этому сайту http://msdn.microsoft.com/en-us/library/678hzkk9.aspx Двойники на самом деле содержат от 15 до 16 значащих цифр вместо 17.

@Jon Skeet decimal больше подходит, чем double, из-за его более высокой точности, 28 или 29 значащих десятичных знаков.Это означает меньшую вероятность того, что накопленные ошибки округления станут значительными.Типы данных с фиксированной запятой (то есть целые числа, представляющие центы или 100-ю долю цента, как я видел ранее), подобные упоминаниям Boojum, на самом деле подходят лучше.

Поскольку decimal использует масштабный коэффициент, кратный 10, такие числа, как 0,1, могут быть точно представлены. По сути, десятичный тип представляет это как 1/10 ^ 1, тогда как double будет представлять это как 104857/2 ^ 20 (в действительности это будет больше похоже на действительно большое число) / 2 ^ 1023).

decimal может точно представлять любое базовое значение 10, содержащее до 28/29 значащих цифр (например, 0,1). double не может.

Насколько я понимаю, большинство финансовых систем выражают валюту, используя целые числа, то есть считая все в центах.

IEEE двойной точности на самом деле может представлять все целые числа точно в диапазоне от -2 ^ 53 до + 2 ^ 53. (Восторг Хакера, стр. 262). Если вы используете только сложение, вычитание и умножение, и сохраняете все в целые числа в этом диапазоне, то вы не должны видеть потери точности. Однако я бы очень опасался деления или более сложных операций.

Использование double, когда вы не знаете, что делаете, не подходит.

"двойной" может представлять собой сумму в триллион долларов с погрешностью в 1/90 процента.Таким образом, вы получите высокоточные результаты.Хотите подсчитать, сколько стоит отправить человека на Марс и вернуть его обратно живым?двойной подойдет в самый раз.

Но в отношении денег часто существуют очень конкретные правила, гласящие, что определенный расчет должен дать определенный результат и никакой другой.Если вы рассчитаете сумму, которая очень-очень близка к 98,135 доллара, то часто будет действовать правило, которое определяет, должен ли результат составлять 98,14 доллара или 98,13 доллара, и вы должен следуйте этому правилу и получите требуемый результат.

В зависимости от того, где вы живете, использование 64-битных целых чисел для обозначения центов, пенни, копеек или любой другой наименьшей единицы измерения в вашей стране обычно работает просто отлично.Например, 64-разрядные целые числа со знаком, представляющие центы, могут представлять значения до 92,223 триллиона долларов.32-битные целые числа обычно не подходят.

Нет, у двойника всегда будут ошибки округления, используйте " десятичную " если вы на .Net ...

Фактически double с плавающей точкой идеально подходит для представления денежных сумм, если вы выберете подходящую единицу.

См. http://www.idinews.com/moneyRep.html

То есть long с фиксированной запятой. Любой из них потребляет 8 байт, что, безусловно, предпочтительнее, чем 16 байт, потребляемых элементом десятичного .

Работает ли что-то или нет (то есть дает ожидаемый и правильный результат) - это не вопрос голосования или индивидуального предпочтения. Техника либо работает, либо нет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top