LINUX.ORG.RU

Точность double

 , ,


0

1

Есть код.

Math.cos(Math.toRadians(90));

Math.sin(Math.toRadians(90));

В первом случае я получаю очень близкое к 0 число но не точно 0; Это понятно. Но почему во втором случае я получаю точно 1.0 , а не 1.0000…чтототам ?

★★

Последнее исправление: tyamur (всего исправлений: 2)
Ответ на: комментарий от thunar

Ну это понятно. Ну а для углов отличных от нуля?

tyamur ★★
() автор топика

ЕМНИП в double 52 бита отводится на мантиссу, ну значит и точность на вскидку 2**-52 ну или по-нашему 10**-17, у меня нули в вычислениях примерно такого порядку во всяком случае.

А ежели брать числа с одинарной точностью, то там будет где-то 10**-6 всего лишь.

luke ★★★★★
()

Но почему во втором случае я получаю точно 1.0 , а не 1.0000…чтототам ?

Округление. Вообще, зависит от того, что за процессор у тебя, и каким транслятором ты пользуешься.

luke ★★★★★
()
  1. вещественные числа на ПК имеют запас точности и все операции выполняются с некоторой степенью точности(грубо говоря по числу знаков) и могут в дальнейшем ещё и округлятся

  2. как пример сложение 6.1232339957368e-17(мой результат косинуса) с нулём то совершенно логично получим 6.1232339957368e-17, но если мы будем складывать с 1.0, то прежде всего 6.1232339957368e-17 будет выровнено по порядку(степени) под 1.0, но из-за этого оно будет терять знаки после точки грубо говоря будет такая последовательность переходов

6.1232339957368e-17
0.6123233995736e-16
0.0612323399573e-15
0.0061232339957e-14
0.0006123233995e-13
...
0.0000000000006e-04
0.0000000000000e-03
...
0.0000000000000e-00 -> готово, число того же 
порядка что и 1.0e00 и вот теперь складывая с ним мы получим 1.0, логика отброса состоит в том, чтобы отбрасывать наимение значащие части числа

Т.е. вся веселуха произошла из-за ограниченной точности double и арифметики, которая по сути требует для например сложения и вычитания приравнивать порядки и уже после выполнять действия, в остальном как уже рекомендовали стоит посмотреть статьи на данную тему или как вариант кусочек главы по этой теме из книги «Игровой движок» 3-е издание

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 1)
Ответ на: комментарий от luke

Получается для sin результат тоже получился не точно 1.0 Просто значение после точки получилось дальше и соответственно отбросились.

tyamur ★★
() автор топика
Последнее исправление: tyamur (всего исправлений: 1)
Ответ на: комментарий от tyamur

Да. Именно так. При выполнении арифметики чисел сильно отличающихся порядков, выравнивание порядков может сносить порядочную часть мантиссы(значащей части), вплоть до её обнуления.

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 1)

Скорее всего потому, что

cos(pi/2+eps) = eps + …,

sin(pi/2+eps) = 1 - eps^2 / 2 + …

…Если еще подробнее, то если для косинуса (в окрестности pi/2) погрешность в 16-естнадцатом (десятичном) знаке аргумента даст погрешность в 16 знаке результата, то для синуса – даст ошибку в 32 знаке, т.е. уже за пределами хранимой мантиссы.

Zeta_Gundam
()
Последнее исправление: Zeta_Gundam (всего исправлений: 1)
Ответ на: комментарий от tyamur

Получается для sin результат тоже получился не точно 1.0 Просто значение после точки получилось дальше и соответственно отбросились.

Кто тебе мешает сравнить Math.sin(Math.toRadians(90)) с 1.0??????????????????????????????????????????????????? Чё ты гадаешь как цыганка?????????????????????????????

anonymous
()
Ответ на: комментарий от anonymous

«A computation is a temptation that should be resisted as long as possible.»

Если ты не понимаешь, что и как вычисляется, то результат тебе тоже не поможет.

Zeta_Gundam
()
Ответ на: комментарий от tyamur

Если тебе реально интересно, глянь вот сюда как типы float и double устроены в железе: http://datasheets.chipdb.org/Intel/x86/808x/datashts/8087/205835-007.pdf

Емнип первый IEEE стандарт для чисел с плавающей точкой был сделан на основе i8087.

Там правда тоже есть проблема с округлением: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323#c70

luke ★★★★★
()
Ответ на: комментарий от anonymous

Так у меня и получилось в итоге 1.0

tyamur ★★
() автор топика
Ответ на: комментарий от tyamur

Способ округления хвоста настраивается, в цпп есть соответствующий интерфейс, должен настраивать фпу. Т.е это не обязательно отброс. https://en.cppreference.com/w/cpp/numeric/fenv/FE_round

pavlick ★★
()
Последнее исправление: pavlick (всего исправлений: 1)

Интересно, если на ЛОРе спросить про расходимость интегрирования по Эйлеру, то в ответ тоже предложат почитать про машинную арифметику?

ТС, овладей рядами Тейлора! Только матан научит правильно считать трансцендентные функции.

Zeta_Gundam
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.