|
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
|
|
Как обнаружить потерю точности при умножении двух double14.09.2025, 12:13. Показов 5118. Ответов 66
Добрый день,
Пытаюсь разобраться для себя с такими интересными тонкостями вещественной арифметики, как потеря точности и переполнения. Со сложением и вычитанием ясно: если одно из чисел не равно 0, а результат равен второму - значит произошла потеря точности. Но как быть с умножением? Ведь там при потери точности произведение будет равно не одному из множителей, а просто некоему неправильному числу???
0
|
|
| 14.09.2025, 12:13 | |
|
Ответы с готовыми решениями:
66
[Error] cannot convert 'double (*)(double)' to 'double' for argument '1' to 'double pow(double, double)' Найти все двузначные числа, которые при умножении на 2 заканчиваются на 8, а при умножении на 3 - на 4. Ошибка: error LNK2001: unresolved external symbol "double __cdecl Akk(double,double,double)" |
|
6279 / 3003 / 1051
Регистрация: 01.06.2021
Сообщений: 11,251
|
||
| 15.09.2025, 15:55 | ||
|
Как ни крути, если что-то серьезное, все равно нужно перейти на дроби с целыми числами и все вычисления делать в целых числах.
0
|
||
|
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
|
||
| 15.09.2025, 18:59 [ТС] | ||
1
|
||
|
Нарушитель
622 / 380 / 67
Регистрация: 09.03.2016
Сообщений: 4,166
|
|
| 15.09.2025, 23:12 | |
|
Если вы все пишете, что это действительно необходимо. Как нибудь... Спасибо автору конечно...
0
|
|
| 16.09.2025, 22:02 | ||
|
Рендерим 3D сцену, есть точка L, например, возможно, источник света. Из нее выбрасываем луч в направлении dir (вектор 3 флота). Луч пересекает какой-то объект в точке p. Известна нормаль N в этой точке (необязательно она нужна). Все хорошо. Теперь мы хотим как бы "ощупать лучами" окрестность точки p. Для этого генерируем напр 100 случайных точек (p1..p100) в радиусе R, для каждой вычисляем направление, напр Vec3f dir1 = (p1 - L).normallized(); Ну и бросаем лучи в этих направлениях из той же точки L. Да, но есть погрешность флота, и dir1 не будет вычислено точно, возможно при достаточно большом расстоянии между L и p в радиус R мы даже не попадем. На какой радиус мы можем рассчитывать? Все флоты 4 байта, увы, изменить это не можем
0
|
||
| 17.09.2025, 12:02 | |
|
И вот мелочь, легко забыть (и забыл). В лекции не упоминается волшебное слово/термин GPU, а сейчас так нельзя. Этот гад double не любит. И "расширенные" команды процессора (sse и все такое) - вроде там double и есть, но, судя по коду библиотек, 4-байтовые доминируют.
0
|
|
|
Супер-модератор
|
||||
| 17.09.2025, 14:40 | ||||
0
|
||||
| 17.09.2025, 16:55 | |||
Но программист не только "имеет право", но и обязан использовать все вычислительные мощности, поэтому гонорировать аспект GPU в наше время, мягко говоря, недальновидно/инфантильно- Бросаем луч из исходной точки L в точку "прицела" p1. Насколько луч отклонится от p1 за счет погрешности float? При этом исходные точки могут иметь координаты далеко не единичные. Мульены вряд ли, таких сцен избегают. А вот тыщи или даже 10 тыс - вполне. Также известно как задавалась точка прицела p1: она в плоскости с нормалью N проходящей через базовую точку p
1
|
|||
|
6279 / 3003 / 1051
Регистрация: 01.06.2021
Сообщений: 11,251
|
||
| 17.09.2025, 17:10 | ||
|
Igor3D, при чем тут вообще GPU? Тема в разделе С++. В этом языке вычисления с числами с плавающей запятой выполняются на CPU.
Вычисления могут быть выполнены на GPU, если используется специальная библиотека или фреймворк для параллельных вычислений, например, CUDA или OpenCL, которые позволяют перенести вычисления на графический процессор. Но если мы говорим просто о С++, то все вычисления там осуществляются на CPU с использованием набора инструкций FPU (Floating Point Unit) или SSE/AVX (для векторизации - оптимизации программы с использованием векторных расширений системы команд процессора). Грубо говоря, все обычные вычисления с плавающей запятой выполняются на FPU процессора. И то, что 4-байтовый float предпочтительнее, чем double, актуально только для вычислений на GPU, поскольку всякие CUDA действительно лучше работают с 4-байтовыми числами. Однако, для современных CPU, не будет никакой разницы - float или double, особенно, если нет ограничений по памяти. Поэтому, Catstail правильно говорит, что в С++ дефолтно нужно выбирать double и не морочиться с низкой точностью float.
1
|
||
|
359 / 121 / 8
Регистрация: 19.07.2024
Сообщений: 627
|
||
| 17.09.2025, 17:34 | ||
|
Но если речь только про ПК - то да, на ПК лучше всегда использовать double. Насколько знаю - на ПК нет разницы в скорости double vs float. (Хотя тут нет полной уверености)
0
|
||
|
6279 / 3003 / 1051
Регистрация: 01.06.2021
Сообщений: 11,251
|
||
| 17.09.2025, 18:00 | ||
|
0
|
||
| 17.09.2025, 18:10 | ||||
Только спокойно работать в double удается весьма редко. Тот же пример выше, луч-то не пальцем надо бросать, а либа юзает float. Тот же движок физики и др Наоборот, львиная доля людей занимается именно этим, не Вы ли работаете с Годот?Добавлено через 4 минуты
0
|
||||
|
6279 / 3003 / 1051
Регистрация: 01.06.2021
Сообщений: 11,251
|
|||
| 17.09.2025, 18:13 | |||
|
Godot как раз исключение - встроенный float это 64-битный плюсовый double (годот написан на плюсах). Вот тут об этом сказано: https://docs.godotengine.org/e... float.html
0
|
|||
|
359 / 121 / 8
Регистрация: 19.07.2024
Сообщений: 627
|
||
| 17.09.2025, 19:57 | ||
|
PS: А если в приоритете точность, и скоростью вычислений можно пожертвовать, то может имеет смысл топикстартеру озаботиться созданием своего (нового) численного типа: скажем назовём его QuadFloat. 16-байтного размера. Или даже ещё бОльшего размера. С увеличенной соответственно мантиссой (а может и экспонентой). И все расчёты выполнять на нём. Ну или (как уже выше писал) - создать тип fixed point большой длины. Такой, чтобы вмещал весь диапазон чисел, необходимый в его расчётах. Это если сложно реализовать свой QuadFloat.
0
|
||
|
-73 / 64 / 2
Регистрация: 23.11.2024
Сообщений: 805
|
|
| 17.09.2025, 21:00 | |
|
0
|
|
| 17.09.2025, 21:19 | ||||
Справедливости ради, это было лет 15 назад, не исключено что сейчас уже работает.Гораздо полезнее уметь оценить погрешность/ошибку (см задачу выше), но этим заниматься никто не хочет, и понятно почему: думать надо, легко ошибиться. А вот рассказывать что 8 байт лучше чем 4 - легко и приятно
0
|
||||
|
Модератор
|
|
| 18.09.2025, 19:30 | |
|
Существуют алгоритмы, повышающие точность вычислений с плавучкой.
По большому счёту, это подобие длинной арифметики, когда за счёт дополнительной переменной увеличивается разрядность. Ну и время выполнения - тоже увеличивается. Для сложения - алгоритм Коха. Для умножения я не знаю, но, наверняка, есть. Также встречал правила изменения порядка вычислений - чтобы избежать "потерю" маленького числа на фоне значительно большего. Для этого есть множество формул преобразования и они подбираются под каждый уникальный случай.
0
|
|
|
6279 / 3003 / 1051
Регистрация: 01.06.2021
Сообщений: 11,251
|
||||||||||||||||||||||||
| 18.09.2025, 21:09 | ||||||||||||||||||||||||
|
Даже если использовать арифметику произвольной точности, то на первый взгляд покажется, что ответ 0. Потому что всем лень что-то там оценивать. Можете сами попробовать вычислить значение данного выражения в Maxima, Maple, Mathematica. Последняя СКА хотя бы предупреждает, что не хватает машинной точности (точности для внутренних расчетов), хотя реализация n-digit точности в WM просто ломается. Ломается она и в Maple. Для тех, кто не знает, объясняю. В программах арифметики произвольной точности используется machine precision. Именно этот вид точности, например, указывается во многих СКА. machine precision это точность внутренних расчетов. Однако, в Mathematica и Maple решили пойти дальше и кроме machine precision, они реализовали еще более удобную фичу: n-digit precision - это когда ты указываешь, сколько значащих цифр должны быть корректны. n-digit precision можно использовать, например, в функции N[] или evalf. Однако, выражение выше - яркий пример того, что реализация n-digit precision данных СКА не справляется. Но даже в документации WM написано, что:
Программы просто выводят 0. У человека могут возникнуть сомнения, что ответ 0, поэтому он может попробовать увеличить машинную точность. Но даже если выбрать точность в 400 знаков, он все равно получит 0. Тут он подумает "ну значит результат и вправду 0" и тем самим совершит ошибку.
0
|
||||||||||||||||||||||||
|
2450 / 1595 / 738
Регистрация: 17.03.2022
Сообщений: 5,166
|
||
| 18.09.2025, 21:18 | ||
|
Просто нормальному программисту-вычислителю попытки счета подобного "в лоб" должны разве что сниться в качестве ночных кошмаров. А если делать все нормально, то содержательных проблем не возникнет.
0
|
||
|
6279 / 3003 / 1051
Регистрация: 01.06.2021
Сообщений: 11,251
|
|||
| 18.09.2025, 21:25 | |||
|
на мой взгляд, как ни крути, машинную точность нужно подбирать методом тыка. Конечно, я бы хотел подать на ввод программе выражение и количестве значащих цифр, которые я хочу получить в результате, и чтобы она в ответ указала какую машинную точность мне нужно использовать в расчётах. Но как я написал выше, такую программу не создать.
0
|
|||
| 18.09.2025, 21:25 | |
|
Ошибки error C2296: -: недопустимо, левый операнд имеет тип "double (__cdecl *)(double,double,double Создать функцию с параметрами GetFunctionValue(double& a, double& b, double& c, double& x)... Реализовать в виде GetFunctionValue(double& a, double& b, double& c, double& x) Реализовать в виде GetFunctionValue(double& a, double& b, double& c, double& x) Реализовать в виде GetFunctionValue(double& a, double& b, double& c, double& x) Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
[golang] Worker Pool
alhaos 09.06.2026
Worker Pool
Worker Pool — паттерн конкурентной обработки задач в Go.
Суть: фиксированное количество горутин-воркеров читают задачи из общего канала
и пишут результаты в общий канал результатов. . . .
|
[golang] Pipeline
alhaos 08.06.2026
Pipeline
Pipeline — паттерн конкурентной обработки данных в Go.
Суть: данные проходят через цепочку независимых стадий, каждая из которых работает в своей горутине и общается с соседями через. . .
|
Свет внутри себя
kumehtar 07.06.2026
Пусть это будет здесь
lIs4oanZS9Y
|
Программа для com-порта
Uhbif79 05.06.2026
Всем привет, давно хотел изучить Qt, начинал, бросал, потом снова начинал. И сейчас вот смог написать свою первую программу.
До этого имел опыт программирования микроконтроллеров, писал прошивки на. . .
|
|
Транскрипция 55-минутного видео через Whisper: WhisperDesktop облажался, спас Google Colab[
anaschu 01.06.2026
Понадобилось получить текст из свежезагруженного видео на YouTube. Казалось бы, задача на пять минут. Заняла полтора часа. Делюсь опытом — может кому пригодится последовательность решений.
. . .
|
21 мат мед. Планы на развитие модели здравоСохранения
anaschu 01.06.2026
AnyLogic: план развития симуляционной модели рабочего коллектива — динамический абсентеизм, реальные данные, три сценария сравнения
Продолжаю серию постов о дискретно-событийной модели рабочего. . .
|
20. Мат мед. Абсентеизм как отдельный тип простоя
anaschu 29.05.2026
Апдейт модели: исправленные баги, абсентеизм и новые механизмы
Продолжаю развивать ранее описанную модель рабочего коллектива на AnyLogic. За последние несколько дней был проведён серьёзный. . .
|
19. здоровье, усталость и психотип работника влияют на производительность предприятия, и наоборот, производительность на здоровье, усталось и психотип
anaschu 28.05.2026
Дискретно-событийная модель рабочего коллектива на AnyLogic: здоровье, выгорание, психотипы и микростимуляция
Привет, коллеги. Хочу поделиться итогами нескольких недель работы над симуляционной. . .
|