SuperMiQi Ответов: 3

Как получить правильный результат деления в C# ?


Всем Привет,

У меня есть следующий вопрос:

float increment = 0.00025f;
float sampleFreq = 1.f / increment;
[+] sampleFreq = 3999.99976
а не 4000 почему ?

Как я могу получить ожидаемый результат 4000 (не с помощью метода округления) ?

Конечно, что-то глупое.

Заранее Вам большое спасибо.
Мики

Что я уже пробовал:

Я попробовал с двойным, тем же результатом.

3 Ответов

Рейтинг:
22

Rob Philpott

Это немного математично, но поплавки и двойники-это типы с плавающей запятой, которые имеют показатель основания 2 в отличие от основания 10, к которому мы, люди, привыкли. Некоторые числа не могут быть представлены точно в этом (а также в нашей базе 10, если уж на то пошло, подумайте 1/3 = 0.33333333333...), и там, где это происходит, вы получаете некоторую потерю точности.

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

Вы можете попробовать использовать десятичный тип в файле .NET. Это использует базовый показатель 10, поэтому ведет себя так, как вы ожидаете (в основном), но это связано с затратами с точки зрения занимаемой площади и производительности.


SuperMiQi

Большое вам спасибо, что это решение проблемы. Теперь я получаю правильный ожидаемый результат.

Рейтинг:
14

Dave Kreskowiak

Потому что вы используете тип данных float. Он не может точно представлять числа с плавающей запятой. Почитайте об этом: здесь[^] и здесь[^] .

Подумайте об этом. Как вы представляете бесконечное число значений в конечном числе битов? Ты не можешь. Приходится идти на жертвы, чтобы создать тип данных, который может представлять широкий диапазон наиболее часто используемых значений и обеспечивать некоторую степень "точности".

Вы можете использовать тип decimal[^] вместо. Это 128-битный тип, созданный для более высокой точности для таких вещей, как финансовые цели, но имеет меньший диапазон значений, которые он может представлять.


Рейтинг:
12

TheRealSteveJudge

Точность поплавка и двойника недостаточна.

decimal increment = 0.00025M;
decimal sampleFreq = 1M / increment;

Вместо этого используйте десятичную дробь.


SuperMiQi

Большое вам спасибо, что это решение проблемы. Теперь я получаю правильный ожидаемый результат.

TheRealSteveJudge

ВТФ? Мое решение правильное. Спасибо за downvoting!

TheRealSteveJudge

Пожалуйста. Еще один человек отклонил мое решение. :-(

SuperMiQi

Хм. это было далеко от моего намерения, я принял оба комментария, чтобы поблагодарить всех.

SuperMiQi

а-ля-ля, как это исправить.