2016-01-19 2 views
1

простой плавающей точкой присоединения х + у в точности с 4 (т.е. IEEE мантисса шириной 3), с 3-мя битами для показателя (emax=3, emin=-4) для x = mpfr('0.75'), y = mpfr('0.03125') неправильно дает mpfr('0.75') как результат, когда он должен быть mpfr('0.8125'). Обратите внимание, что 0.3125 является субнормальным числом для этого уменьшенного формата точности.Это ошибка в gmpy2 python?

Редактирование: взаимодействие терминала извлечено из ссылки и включено для дальнейшего использования.

>>> "{0:.10Df}".format(mpfr('0.75')+mpfr('0.03125')) 
'0.7500000000' 
>>> get_context() 
    context(precision=4, real_prec=Default, imag_prec=Default, 
    round=RoundToNearest, real_round=Default, imag_round=Default, 
    emax=3, emin=-4, 
    subnormalize=True, 
    trap_underflow=False, underflow=False, 
    trap_overflow=False, overflow=False, 
    trap_inexact=False, inexact=True, 
    trap_invalid=False, invalid=False, 
    trap_erange=False, erange=False, 
    trap_divzero=False, divzero=False, 
    trap_expbound=False, 
    allow_complex=False) 
>>> 

ответ

4

Отказ от ответственности: Я поддерживаю gmpy2.

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

Update

Проблема не связана с созданием субнормальным из строки. В этом случае субнормальное значение создается должным образом. В gmpy2 2.0.x существует редкая ошибка при преобразовании строки в субнормальное. Самый простой способ - сначала преобразовать вход в тип mpq; т.е. mpfr(mpq('0.03125')).

Актуальной проблемой является режим округления по умолчанию. Промежуточная сумма находится на полпути между двумя 4-битными значениями. Режим округления по умолчанию RoundToNearest выбирает округленное значение с окончательным битом 0. Если вы измените режим округления на RoundUp, вы получите ожидаемый результат.

>>> from gmpy2 import * 
>>> ctx=context(emax=4, emin=-4, precision=4) 
>>> set_context(ctx) 
>>> a=mpfr('0.75') 
>>> b=mpfr('0.03125') 
>>> "{0:.10Df}".format(a+b) 
'0.7500000000' 
>>> get_context().round=RoundUp 
>>> "{0:.10Df}".format(a+b) 
'0.8125000000' 

последнее замечание: значения precision, emax и emin являются незначительно отличаются между IEEE стандартами и библиотеки MPFR. Если e является размер и показатель p является точность (в терминах IEEE), то precision должно быть p+1, emax должно быть 2**(e-1) и emin должно быть 4-emax-precision. Это не влияет на ваш вопрос, так как он меняет только emax.

+0

Спасибо за супер быстрый ответ. Могу ли я загрузить версию разработки, на которую вы ссылаетесь, где ошибка может быть исправлена? Это в его github [репозиторий] (https://github.com/aleaxit/gmpy)? Если да, то какую ревизию я должен проверить? – user1779685

+0

Просто возьмите последнюю версию github. Он должен работать для тестирования этой проблемы. – casevh

+0

Спасибо, что посмотрели на это так быстро. Я должен использовать RoundToNearest, поэтому другой режим округления не вариант для меня. Я попробовал упомянутое исправление с помощью mpq, но он не сработал: дал 0.75 еще раз. Я использую gmpy2-2.0.3. Спасибо за указание на ошибку в emax: можете ли вы упомянуть общую формулу для получения emin для общего e, p (4, похоже, относится к моему примеру?)? – user1779685

 Смежные вопросы

  • Нет связанных вопросов^_^