Вопрос

все, что я пытаюсь реализовать библиотеку арифметики с плавающей запятой, и у меня проблемы с пониманием алгоритма вычитания чисел с плавающей запятой.Я успешно реализовал сложение, и я думал, что вычитание было просто частным случаем этого, но, похоже, я где-то допускаю ошибку.Я добавляю код сюда просто для справки, в нем есть много понятных функций, но я не ожидаю, что кто-то поймет его на 100%.С чем я хотел бы получить помощь, так это с алгоритмом.Мы следуем тому же методу, что и при добавлении чисел с плавающей запятой, за исключением того, что когда мы добавляем мантиссы, мы преобразуем отрицательную единицу (ту, которую мы вычитаем) в дополнение к двум, а затем добавляем их?

Это то, что я делаю, но результат неправильный.Хотя это и очень близко ...но не то же самое.У кого-нибудь есть какие-нибудь идеи?Заранее спасибо!

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

_float subFloat(_float f1,_float f2)
{
unsigned char diff;
_float result;

//first see whose exponent is greater
if(f1.float_parts.exponent > f2.float_parts.exponent)
{
    diff = f1.float_parts.exponent - f2.float_parts.exponent;

    //now shift f2's mantissa by the difference of their exponent to the right
    //adding the hidden bit
    f2.float_parts.mantissa = ((f2.float_parts.mantissa)>>1) | (0x01<<22);
    f2.float_parts.mantissa >>= (int)(diff);//was (diff-1)

    //also increase its exponent by the difference shifted
    f2.float_parts.exponent = f2.float_parts.exponent + diff;
}
else if(f1.float_parts.exponent < f2.float_parts.exponent)
{
    diff = f2.float_parts.exponent - f1.float_parts.exponent;
    result = f1;
    f1 = f2;        //swap them
    f2 = result;

    //now shift f2's mantissa by the difference of their exponent to the right
    //adding the hidden bit
    f2.float_parts.mantissa = ((f2.float_parts.mantissa)>>1) | (0x01<<22);
    f2.float_parts.mantissa >>= (int)(diff);

    //also increase its exponent by the difference shifted
    f2.float_parts.exponent = f2.float_parts.exponent + diff;
}
else//if the exponents were equal
  f2.float_parts.mantissa = ((f2.float_parts.mantissa)>>1) | (0x01<<22); //bring out the hidden bit




//getting two's complement of f2 mantissa
f2.float_parts.mantissa ^= 0x7FFFFF;
f2.float_parts.mantissa += 0x01;



result.float_parts.exponent = f1.float_parts.exponent;
result.float_parts.mantissa = (f1.float_parts.mantissa +f2.float_parts.mantissa)>>1;
                                                //gotta shift right by overflow bits

//normalization
if(manBitSet(result,1))
    result.float_parts.mantissa <<= 1;  //hide the hidden bit
else
    result.float_parts.exponent +=1;

return result;

}
Это было полезно?

Решение

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

Необходимо ли выполнять сложение этих двух элементов, а не вычитание?

Если проблема не в этом, то у меня возникли проблемы с вашим алгоритмом.Прошло много времени с тех пор, как я делал что-либо подобное.Не могли бы вы предоставить некоторые подробности?Более конкретно, что такое скрытый бит?

Мне кажется возможным, что обработка скрытого бита подходит для сложения, но не для вычитания.Может быть, вам следует установить его в мантиссе f1, а не в f2?Или отрицать мантиссу f1 вместо f2?

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

Редактировать:Хорошо, я просмотрел ссылки в вашем комментарии.Одна вещь, которую вы не можете сделать в предоставленном коде, - это нормализация.При добавлении либо скрытые биты переполняются (сдвигают мантиссу влево, увеличивают показатель степени), либо этого не происходит.При вычитании произвольные части мантиссы могут быть равны нулю.В десятичной системе счисления рассмотрите возможность сложения 0.5E1 и 0.50001E1;вы получили бы 1.00001E1, и если бы вы были нормализованы, вы бы получили 0.10001E2.При вычитании 0.5E1 из 0.50001E1 получается 0.00001E1.Затем вам нужно сдвинуть мантиссу влево и уменьшить показатель степени на столько, на сколько потребуется, чтобы получить 0,1E-4.

Другие советы

a-b == a+(-b), а унарный минус тривиален, поэтому я бы даже не стал заморачиваться с двоичным минусом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top