2012-01-18 1 views
5

Я работаю над подпрограммой оптимизации Nelder-Mead в C, которая включает в себя получение среднего значения двух float s. В редких (но вполне воспроизводимых) обстоятельствах два float s, скажем x и y, отличаются только наименее значимым значком их знака. Когда среднее значение принимается, ошибки округления подразумевают, что результатом будет либо x, либо y.Как указать, в каком направлении округлить среднее из двух поплавков, которые отличаются LSB от их значения?

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

(Как) могу ли я это сделать?

+3

Не можете ли вы сравнить эти два поплавка и установить округление до нуля, минус бесконечность или плюс бесконечность в зависимости от результата сравнения? –

+0

Но вы можете определить в то время, когда вы округляете ли 'x> y', правильно? –

+0

Вы могли бы, но есть намного более простой способ сделать это. –

ответ

2

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

double average(double x, double y) { 
    double a = 0.5*(x+y); 
    return (a == x) ? y : a; 
} 
+0

Вот что я собирался предложить. Независимо от режима округления, 'a' может только равняться' x', если (a) выполнено описанное условие, или (b) 'x == y'. В обоих случаях это дает желаемый результат и делает это очень эффективно. –

0

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

значения, представляющие интерес:

  • Когда значения имеют одинаковый знак и показатель и отличается только одним мантиссы.

  • Когда значения имеют один и тот же знак, экспоненты отличаются на единицу, а единица с более крупным показателем имеет мантисса 0, а другая мантисса, заполненная единицами.

В самом деле, если вы используете IEEE-754 номера (которые вы, вероятно,) вы можете выполнить оба теста сразу (после проверки на такие вещи, как Zero, Inf и NaN):

if ( repr1 + 1 == repr2 
    || repr2 + 1 == repr1) 
    .... 

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

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