Как работает десятичная дробь? - PullRequest
4 голосов
/ 18 февраля 2011

Я посмотрел на десятичную в C #, но я не был уверен на 100%, что он сделал. Это с потерями? в C # запись 1.0000000000001f+1.0000000000001f приводит к 2 при использовании float (double возвращает вас 2.0000000000002, что правильно) возможно ли добавить две вещи с десятичной дробью и не получить правильный ответ?

Сколько десятичных знаков я могу использовать? Я вижу MaxValue 79228162514264337593543950335, но если я вычту 1, сколько десятичных разрядов я могу использовать?

Есть ли причуды, о которых я должен знать? В C # его 128 бит, на другом языке, сколько это битов, и будет ли он работать так же, как в C # decimal? (при сложении, делении, умножении)

Ответы [ 3 ]

14 голосов
/ 18 февраля 2011

То, что вы показываете, не decimal - это float.Они очень разные типы.f - это суффикс для float, он же System.Single.m - это суффикс для decimal, он же System.Decimal.Из вашего вопроса не ясно, думали ли вы, что на самом деле это был decimal, или вы просто использовали float для демонстрации своих страхов.

Если вы используете 1.0000000000001m + 1.0000000000001m, вы получите точноправильное значение.Обратите внимание, что, кстати, версия double не могла точно выразить ни одно из отдельных значений.

У меня есть статьи по обоим видам с плавающей запятой в .NET, и вы должны прочитать их полностью,наряду с другими ресурсами:

Конечно, все типы с плавающей запятой имеют свои пределы, но, в частности, вы должны не ожидать, что двоичная с плавающей запятой будет точно представлять десятичные значения, такие как 0,1.Тем не менее, он не может представлять что-либо, что не может быть точно представлено в 28/29 десятичных цифрах - поэтому, если вы разделите 1 на 3, вы, конечно, не получите точного ответа.

Вы также должны отметитьчто диапазон decimal значительно меньше, чем double.Таким образом, хотя он может иметь точность 28-29 десятичных цифр, вы не можете представлять действительно огромные числа (например, 10 200 ) или минимальные числа (например, 10 -200 ).

0 голосов
/ 18 февраля 2011

Точка плавания по своей сути неточна. Некоторые числа не могут быть представлены верно. Десятичная дробь - это большая плавающая точка с высокой точностью. Если вы посмотрите на страницу msdn , вы увидите, что «28-29 значащих цифр». Классы .net Framework не зависят от языка. они будут работать одинаково на каждом языке, который использует .net.


edit (в ответ на Jon Skeet): Если вы инициализируете класс Decimal указанными выше числами, которые не превышают 28 цифр после десятичной запятой, число будет сохраняться с точностью до тех пор, пока двоичное представление является точным. Поскольку он работает в 64-битном формате, я предполагаю, что 128-битный будет отлично с ним справляться. Некоторые числа, такие как 0,1, никогда не будут точно представимы, потому что они представляют собой повторяющуюся последовательность в двоичном формате.

0 голосов
/ 18 февраля 2011

Десятичные знаки в программировании (почти) никогда не бывают точными на 100%.Иногда даже лучше умножить десятичное значение на очень большое число, а затем вычислить, но это только в том случае, если вы, например, уверены, что значение всегда находится в диапазоне от 0 до 100 (поэтому оно не выйдет за пределы диапазона максимального значения)

...