Как избежать того, чтобы файл math.sin (math.pi * 2 * VERY LARGE NUMBER) имел намного больший запас ошибок, чем math.sin (math.pi * 2)? - PullRequest
3 голосов
/ 06 марта 2020

Я читал в других вопросах, что, например, sin (2π) не равен нулю из-за представления с плавающей запятой, но очень близок. Эта очень маленькая ошибка не является проблемой в моем коде, так как я могу, например, округлить до 5 десятичных знаков.

Однако при умножении 2π на очень большое число ошибка значительно увеличивается. Ответ должен быть нулевым (или близким), но это далеко от него.

Я что-то делаю в своем мышлении в корне неправильно? Если нет, то как я могу избежать допустимой погрешности с плавающими числами, чтобы π «увеличилось» как число периодов (2 * PI * X) → ∞?

Обратите внимание, что все 3 последних результата являются одни и те же. Может кто-нибудь объяснить, почему это так, хотя 5) точно PI / 2 больше, чем 4)? Даже при огромном смещении в синусоидальной кривой увеличение PI / 2 все равно должно давать другое число, верно?

  1. Проверка небольшого числа SIN (2 * PI)

    print math.sin(math.pi*2)
    

    РЕЗУЛЬТАТ = -2.44929359829e-16 КАК ОЖИДАЕТСЯ → Эта ошибка допустима для моей цели

  2. Добавление PI / 2 к коду выше: SIN (2 * PI + PI / 2)

    print math.sin((math.pi*2)+(math.pi/2))
    

    РЕЗУЛЬТАТ: 1.0 КАК ОЖИДАЕТСЯ

  3. Проверка очень большого числа SIN (2 * PI * ОЧЕНЬ БОЛЬШОЙ НОМЕР) (по-прежнему ожидается близким к нулю)

    print math.sin(math.pi*2*(415926535897932384626433832795028841971693993751))
    

    РЕЗУЛЬТАТ: -0.759488037749 НЕ ОЖИДАЕТСЯ -> Это поле ошибки НЕ подходит для моей цели

  4. Добавление PI / 2 к коду выше: SIN (2 * PI * ОЧЕНЬ БОЛЬШОЙ НОМЕР + PI / 2) (ожидается около 1)

    print math.sin((math.pi*2*(415926535897932384626433832795028841971693993751))+(math.pi/2))
    

    Как и выше, но я добавил PI / 2 - ожидается получение 1,0 в результате
    РЕЗУЛЬТАТ: -0.759488037749 НЕ КАК ОЖИДАЕМЫЙ - почему тот же результат, что и выше, когда я добавил PI / 2 (должен go четверть периода на кривой синуса)

  5. Добавление случайного числа (8) к очень большому n umber, не ожидая ни 1, ни 0

    print math.sin(math.pi*2*(415926535897932384626433832795028841971693993759))
    

    , как указано выше, но я добавил 8 - ожидая, что ни 0, ни 1
    РЕЗУЛЬТАТ: -0.759488037749 НЕ КАК ОЖИДАЕТСЯ - почему тот же результат, что и выше, когда я добавил 8

Ответы [ 3 ]

3 голосов
/ 06 марта 2020

Это просто не будет работать с переменными двойной точности.

Значение math.pi является правильным только для 16 знаков после запятой (53 бита в двоичном формате), поэтому при умножении его по числу, подобному 415926535897932384626433832795028841971693993751 (159 бит), было бы невозможно получить значимые результаты.

Вместо этого вам необходимо использовать математическую библиотеку произвольной точности. Попробуйте использовать mpmath, например. Скажите, что вам нужна точность в 1000 бит, а затем повторите свои суммы:

>>> import mpmath
>>> mpmath.mp.prec=1000
>>> print(mpmath.sin((mpmath.pi*2*(415926535897932384626433832795028841971693993751))+(mpmath.pi/2)))
1.0
2 голосов
/ 06 марта 2020

Как избежать math.sin(math.pi*2*VERY LARGE NUMBER), имеющего намного большую погрешность, чем math.sin(math.pi*2)?

Вы можете % 1 это очень большое число:

>>> math.sin(math.pi*2*(415926535897932384626433832795028841971693993751))
-0.8975818793257183
>>> math.sin(math.pi*2*(415926535897932384626433832795028841971693993751 % 1))
0.0
>>> math.sin((math.pi*2*(415926535897932384626433832795028841971693993751))+(math.pi/2))
-0.8975818793257183
>>> math.sin((math.pi*2*(415926535897932384626433832795028841971693993751 % 1))+(math.pi/2))
1.0
0 голосов
/ 06 марта 2020

Используемые алгоритмы являются приблизительными, а значения (например, пи) являются приблизительными. Так что $ \ pi \ cdot {SomeLargeNumber} $ будет иметь большую ошибку sh (так как значение $ \ pi $ приблизительное). Используемая функция (аппаратно?) Уменьшит аргумент, возможно, используя немного другое значение $ \ pi $.

Обратите внимание, что арифметика с плавающей точкой c не не удовлетворяет аксиомам для реальной арифметики c.

...