.Net и умножение синглов - PullRequest
       22

.Net и умножение синглов

0 голосов
/ 12 ноября 2009

Может кто-нибудь объяснить эту странность:

Dim result as single = 0
result = CType("8.01", Single) * 100 ' result=801.0 as expected
result = CType("8.02", Single) * 100 ' result=802.000061 --- not expected

В дополнение к вышесказанному

result = 8.02 * 100 ' result = 802.0 as expected

Ответы [ 4 ]

2 голосов
/ 12 ноября 2009

Single (или float) имеет только семь значащих цифр, так что все, что может быть напечатано за их пределами, в любом случае является довольно поддельным. Это нормальный артефакт арифметики с плавающей точкой. Вы можете полагаться только на 4 цифры после десятичной точки с вашим номером (так как три значащие цифры уже перед десятичной точкой).

Более подробно, числа 8.01 и 8.02 не могут быть точно представлены с использованием двоичного хранилища (поскольку ни 0,01, ни 0,02 не могут быть представлены точно с суммами долей вида 1/2 n ). Детали могут варьироваться от номера к номеру, но при использовании таких чисел вы можете видеть посторонние цифры вне нормального диапазона точности.

Это не влияет на тот факт, что 801 и 802 могут быть точно представлены , но у вас нет точного номера для начала в этом случае.

ETA: Фактически, то, что вы видите, когда вы включаете вычисление напрямую, заключается в следующем: компилятор оценит вычисление для вас и просто напишет 802 в программу. Вы можете использовать Reflector, чтобы проверить это. Также литералы с плавающей запятой в исходном коде, вероятно, по умолчанию Double, поэтому у вас гораздо большая точность для начала. Если result равно Single, то оно будет понижено до Single, а ошибка в 16-й цифре после десятичной точки просто отбрасывается, поскольку она все равно не может вписаться в Single.

1 голос
/ 12 ноября 2009

Это связано с ограничением представления чисел с плавающей запятой в памяти. Прочитайте страницу википедии для полного отката - это не ошибка или что-то специфическое для .net.

РЕДАКТИРОВАТЬ: эти две статьи тоже стоит посмотреть (последняя тяжелая математика).

0 голосов
/ 12 ноября 2009

Single и Double в .NET представлены как числа с плавающей запятой, и, к сожалению, хранение этих видов чисел не является точным. Вы получите небольшие расхождения при работе с номерами «Single» и «Double».

Однако есть альтернатива - .NET имеет тип Decimal, который гораздо лучше справляется с этими числами. Это все еще не идеально (см. http://www.yoda.arachsys.com/csharp/decimal.html - в частности, последний абзац), но будет гораздо лучше представлять такие количества, как деньги.

0 голосов
/ 12 ноября 2009

Если вам нужно сравнить значения с плавающей запятой, см. Здесь: Сравнение значений с плавающей запятой

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...