От округленной половины до четного денормализованного числа до наименьшего нормального числа в IEEE754 - PullRequest
0 голосов
/ 05 мая 2019

Это очень простой вопрос, но для ответа нужен эксперт.

Как мы знаем, с субнормальным значением с плавающей запятой мы избавляемся от разрыва между 2^emin и 0.

В режиме округления от половины до четного (RTE) мы должны округлить результат с бесконечной точностью как (0.1111...1|r)*2^emin или (1.1111...1|r')*2^(emin-1)?Число слева от точки является неявным битом.

Для первого случая: В статье Что должен знать каждый компьютерщик об арифметических численных вычислениях с плавающей точкой , на рисунке 2 я вижу пространство слева от 2^emin такое же, как пространство справа.Итак, прямо, числовое значение левого числа равно 2^emin - 2^(1-p) (p=24 в flp32).Если мы делаем округление RTE, кажется, что мы должны использовать бит после 24-битного значащего в качестве бита округления (т. Е. (0.111_1111_1111_1111_1111_1111|r)*2^emin, см.

--|---+---+....+-?-|---+---+....+---|-------+........
--0---------------2^emin---------2^emin+1

. Я использую знак вопроса (?) на оси для представленияточка половины

Для второго случая: В стандарте IEEE для субнормального обнаружения перед округлением он говорит «неограниченный» показатель степени блабла. Поэтому, если у нас может быть неограниченный показатель степени, мы можем сдвинутьточный результат до (1.1111...1|r')*2^(emin-1). В этом случае у нас есть половинное левое пространство на 2^emin. Это аналогично всем другим смежным пробелам на 2^e, но после закрытия на 0 на оси числопробелы бесконечны. См.

--|...++++|-+-+-+...|---+---+....+-?-|-------+........
--0-....----------2^emin-1----------2^emin
------| here is keep shrinking

В этом случае кажется, что мы должны округлить точный результат как

(1.111_1111_1111_1111_1111_1111|r')*2^(emin-1)

Путем сдвига на 1 бит влево для результата 1, означает защитный битв этом случае полезен.

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

Ответы [ 3 ]

6 голосов
/ 05 мая 2019

Округление IEEE 754 не указывается в терминах битов округления или защитных цифр.Он задается в терминах действительного числа , которое вычисление произвело бы, если бы мы могли выполнять математику в точной арифметике действительного числа вместо плавающей запятой с ограниченной точностью.

Когда точноезначение вычисления находится точно на полпути между двумя представимыми числами, от округления до половины к четному варианту, чье представление в текущем формате с плавающей запятой будет иметь даже наименее значащую цифру мантиссы.Это также можно рассматривать как округление до опции, которая будет иметь более высокую степень двойки, если обе опции были записаны как нечетное целое число, умноженное на степень двух (и рассматривая 0 как имеющую более высокую степень двух, чем другие числа).

Защитные цифры могут быть задействованы в реализации, если реализация производит указанное поведение округления.IEEE 754 не требует какой-либо конкретной реализации округления, только поведение различных режимов округления.

0 голосов
/ 08 мая 2019

Я нашел это (так как я не эксперт по Python, поэтому я не уверен, достаточно ли это золото):

import numpy as np
import struct
def float_to_hex(f):
    return hex(struct.unpack('<I', struct.pack('<f', f))[0])
if __name__=='__main__':
    min_normal = np.float64(1*(2**-126))
    max_denorm = np.float64(1*(2**-126)-1*(2**-126)*(2**-23))
    # Emin(-126) * (0.111_1111_1111_1111_1111_1111)_11
    n1 = np.float32(max_denorm+min_normal*np.float64(2**-24)+min_normal*np.float64(2**-25))
    # Emin(-126) * (0.111_1111_1111_1111_1111_1111)_10
    n2 = np.float32(max_denorm+min_normal*np.float64(2**-24))
    # Emin(-126) * (0.111_1111_1111_1111_1111_1111)_01
    n3 = np.float32(max_denorm+min_normal*np.float64(2**-25))

    print(float_to_hex(n1))
    print(float_to_hex(n2))
    print(float_to_hex(n3))

python2 on x86_64 linux вывод: 0x800000 0x800000 0x7fffff

выглядит, что python2 по умолчанию следует за round_half_to_even и выбирает бит после 24 битов как значащий бит как бит округления.

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

Ps.Этот отзыв слишком длинный для комментария, поэтому я поместил его здесь @ PatriciaShanahan.

Спасибо, Патриция

0 голосов
/ 07 мая 2019

ОП нуждается в практических способах проверки результатов.У Java есть несколько полезных свойств.Его округление в режиме strictfp соответствует стандарту IEEE754, поэтому оно может служить эталонной реализацией.Эта программа иллюстрирует округление числа ровно посередине между 32-битным минимальным положительным нормальным и наибольшим субнормальным числами.

public strictfp class Test {
  public static void main(String[] args) {
    printIt(Float.MIN_NORMAL);
    printIt(Math.nextDown(Float.MIN_NORMAL));
    double d = ((double)Float.MIN_NORMAL + (double)Math.nextDown(Float.MIN_NORMAL))/2;
    printIt((float)d);
  }
  static void printIt(float f){
    int bits = Float.floatToIntBits(f);
    String s = Integer.toBinaryString(bits);
    while(s.length() < 32){
      s = "0" + s;
    }
    System.out.println(s);
  }
}

Вывод:

00000000100000000000000000000000
00000000011111111111111111111111
00000000100000000000000000000000

В комментарии ОП запросиланализ следующих случаев:

n1=Math.nextDown(Float.MIN_NORMAL) + Float.MIN_NORMAL*(2^-24) + Float.MIN_NORMAL*(2^-25) 

n2=Math.nextDown(Float.MIN_NORMAL) + Float.MIN_NORMAL*(2^-24)

Я предполагаю, что промежуточные вычисления должны быть выполнены в вещественном числе, а не float, арифметическом.

Согласно моим вычислениям, значения действительного числаявляются:

n1=0.111_1111_1111_1111_1111_1111_1011_1111_1111_1111_1111_1110_1 * MIN_NORMAL
n2=0.111_1111_1111_1111_1111_1111_0111_1111_1111_1111_1111_1111 * MIN_NORMAL

Средняя точка между MIN_NORMAL и максимальным субнормальным значением:

0.111_1111_1111_1111_1111_1111_1 * MIN_NORMAL

n1 больше средней точки и поэтому должна округлятьсядо MIN_NORMAL.n2 меньше средней точки и поэтому должно округляться до наибольшей субнормальной.Таковы результаты, которые я получаю от Java.

...