Математика C#. Потолок ошибки или нет?

Я не знаю, почему Потолок ведет себя как в ниже изображения

Почему processingFee! = Настройки. PaymentProcessingFeeInPercentage * prizesSum?

Изображение представления в полном размере

сопроводительный текст http://img514.imageshack.us/img514/3950/csharpceilingproblem.png

10
задан Alin Vasile 1 July 2010 в 14:20
поделиться

7 ответов

Ваш процент не на самом деле 0,05. Это значение , близкое к 0,05 ... и, вероятно, немного больше 0,05. Таким образом, если его умножить на 2600, вы получите значение чуть больше 130,0 ... которое затем будет «потолком» до 131,0.

Используя небольшой инструмент, который я написал недавно (доступен на этой странице о двоичных типах с плавающей запятой .NET), похоже, что фактическое значение float , наиболее близкое к 0,05, составляет 0,0500000007450580596923828125. Для двойников это 0,05000000000000000277555756156289135105907917022705078125.

Мораль истории: не используйте float для подобных вещей - используйте десятичное . Или, если вы просто пытаетесь представить процентное соотношение, если на самом деле может иметь точность только до одного процента, используйте целочисленное значение 0–100.

25
ответ дан 3 December 2019 в 14:33
поделиться

Если вы используете числа с плавающей запятой в крупной банковской операции, не позволяйте мне размещать мои деньги в вашем банке. Используйте десятичных знаков или целых чисел наименьшего общего знаменателя, т. Е. Центов.

Однако вы можете использовать Math.Round , чтобы помочь вам использовать double s или float s, если вы делаете предположения о том, насколько велики ваши вычисления получите. то есть: [

double processingFee = Math.Ceiling( Math.Round( 
    Settings.PaymentProcessingFeeInPercentage * prizesSum, 2 ) );
0
ответ дан 3 December 2019 в 14:33
поделиться

Это результат представления задействованных чисел с плавающей запятой. См. Википедию . Вероятно, 0,05 имеет представление с бесконечной базой 2 как двойное, поэтому значение Math.Ceiling, которое фактически видит Math.Ceiling, может быть немного больше 130.

4
ответ дан 3 December 2019 в 14:33
поделиться

Вы видите неточность плавающей точки.
Фактическое представление 0,05 по основанию 2 немного больше, чем 0,05 , поэтому произведение немного больше, чем 130,0 .
Следовательно, Math.Ceiling округляется в большую сторону.

Измените float s и double s на десятичное .

2
ответ дан 3 December 2019 в 14:33
поделиться

Это связано с тем, что внутренний формат хранения числа с плавающей запятой по своей природе неточен, когда число представлено в десятичном виде. На Stack Overflow есть много-много вопросов по этому поводу.

Число, которое вы возвращаете, вероятно, примерно равно 130.000000000000001, поскольку числа в ваших вычислениях не могут быть представлены точно как двоичное число с плавающей запятой.

1
ответ дан 3 December 2019 в 14:33
поделиться

IMHO, вероятно, это как-то связано с точностью с плавающей запятой. Другими словами, 2600 × 0,05 дает 130,0000 ... 001, а не 130.

Что, если вы попытаетесь сначала округлить результат, чем вызвать Math.Ceiling ?

1
ответ дан 3 December 2019 в 14:33
поделиться

В моем компиляторе, когда я ищу значение умножения, оно говорит 130.00000193715096, так что результат math.ceiling в порядке. Проблема заключается в ограниченной точности типа данных float.

Попробуйте использовать вместо него 'double', если это возможно.

0
ответ дан 3 December 2019 в 14:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: