Почему возникают ошибки вычислений при работе с малыми значениями в C#?

Как я могу модифицировать свой метод построения сетки из точек на здания, чтобы уплотнения сетки в определенных углах были более точными, учитывая, что в основной части сетка строится правильно, но в уплотнениях точки ставятся криво?
Изображение к вопросу
Изображение к вопросу
  • 11 января 2024 г. 5:48
Ответы на вопрос 3
Ошибки вычислений при работе с малыми значениями в C# (или в любом другом языке программирования) обычно возникают из-за ограничений плавающей запятой (floating point). Данные в компьютере представлены в двоичном формате, и для вещественных чисел используется формат, известный как IEEE 754. Этот формат имеет фиксированное количество битов для представления числа и, соответственно, ограниченное количество значащих цифр (точность) и ограниченный диапазон.

Основные причины таких ошибок вычислений включают в себя:

1. Округление: Получаемые значения могут быть не точно представимы в двоичном формате, поэтому они округляются до ближайшего представимого значения.
2. Накопление ошибок: Ошибки округления могут накапливаться при выполнении последовательности вычислений.
3. Потеря значимости: Когда вычисления включают в себя операции с числами сильно различающейся величины, малые значения могут потеряться (undershoot) из-за ограниченной точности.

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

1. Использование типов с большей точностью: В C# стандартными типами для вещественных чисел являются `float` (32 бита) и `double` (64 бита). Если вы используете `float`, переход на `double` может уменьшить ошибки вычислений за счёт увеличения точности. Есть также тип `decimal`, который имеет ещё большую точность (128 бит), но он медленнее и предназначен для финансовых и других вычислений, где точность до последней цифры критична.

2. Изменение алгоритма: Алгоритмы, которые стабильны численно, могут уменьшать эффекты накопления ошибок. Прорабатывайте алгоритм на предмет использования более стабильных математических трансформаций.

3. Контроль погрешности: В случаях, где особенно важна точность, можно вводить дополнительную логику для контроля и коррекции погрешности.

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

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

6. Проверка на краевые условия: Убедитесь, что ваш алгоритм корректно работает с краевыми случаями, где проблемы точности чаще всего проявляются.

7. Использование геометрических библиотек: При работе с геометрией иногда лучше использовать специализированные библиотеки, которые уже содержат необходимые оптимизации и метод
Во-первых, операции с числами с плавающей точкой сами по себе имеют погрешность. Точное значение вряд-ли получишь - разве что очень близкое. 
Есть довольно известные симптомы такого:
- сравнение double или float нужно делать через сравнение их разницы с погрешностью ( (left - right) < delta - это сравнение на равенство)
- довольно известный "прикол" - 0.2 + 0.1 = 0.30000000000000004 (операции неточные)

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

Вывод: погрешности при вычислениях с числами с плавающей точкой - это норма (если так можно назвать). Если нужны более точные расчеты, то и брать нужно соответствующий тип данных, например, decimal
Про числа с плавающей точкой учат ещё в школе на уроках информатики 
https://0.30000000000000004.com/
Похожие вопросы