Доброго времени суток. Подскажите, пожалуйста, решение следующей проблемы. Сопроцессор при соответственно выставленных флагах округления округляет в программе число к нулю (то есть к наименьшему модулю), но... После вычисления логарифма (fyl2x), если не дай боже получилось целое число, он его, зараза, тоже "округляет". То есть получился результат 2, он из него сделает 1, и т.п. Смотрел, сравнивал, разница при непосредственной загрузке и при получении числа в ходе вычисления только в выставленном флаге PE в слове состояния (status word). Но он, вроде, сигнализирует, а не влияет на вычисления. В любом случае, поменять его, возможности не представляется, да и, чувствую, лишняя это работа. Подскажите что-нибудь, а? Ведь, наверняка, решение простое. P.S. Пока-что отделался прибавлением ма-а-а-сюсенького числа, но это на время. Вычисления то нужны - точные.
дело в том, что число, получившееся в сопре, таки было равно не 2, а где-то стремлось к 1.(9) - и его если округлить к нулю, то и будет 1. Так что придётся на момент сохранения или прибавлять число, или округлять до ближайшего. А впрочем какая фиг разница - прибавлять-не прибавлять? Точные вычисления они на то и точные, что без округления... т.е. если округляешь - то или оставь это маленькое число, или поменяй флаги округления.
Округление нужно, чтобы получить правильный результат Нужно получить дробную часть числа. Отескается целая часть, поэтому округление должно быть в сторону нуля. ( 6.987 после округления к нулю = 6, в рез-те дробная часть = 0.987). Да, наверное так и оставлю - с прибавлением числа. Вот только... Пример. Я прибавляю, для примера, ДЕЛЬТА=0.001 (на самом деле меньше, но не суть важно). У меня число: 5.9996. Прибавляю ДЕЛЬТУ, получаю 6.0006. Округляю (получили 6), отнимаю от начального числа и получаю... Дробная часть числа 5.9996 равна (застрелиться и не встать!) -0.0004. Гадство... Взять ДЕЛЬТУ такой маленькой, чтобы сопроцессор ее не переплюнул? Так вроде у него в вычислениях вообще свой формат, по-моему разрядностью куда побольше, чем я могу задать в программе. Гадство...
Хм... А если всё сделать средствами CPU? Т.е. как известно, число типа флоат состоит из знака, мантиссы и экспоненты. Что если нам просто взять из числа экспоненту, и вычислив на её основе количество разрядов, относящихся к целой части числа, просто сдвинуть всю мантиссу с помощью SHL (Не забыв про знак, естестно), а потом отнять это же число от экспоненты? Правда, может получиться UNORM... ну а тут уж дальше BSR и всё такое - приведение к нормированному виду.
ABCetc Непонимаю чем тебе результат не устраивает? Все точно. Было 1,(9) округлили получили целую 1 вычли дробную 0,(9) И что это на алгоритм повлияет? Помойму нет.
2 Pavia Мне целая часть тоже нужна. Правильная. В том-то и фокус, что с 1.9 это прокатывает, а с целыми числами- нет. Еще раз повторю: после вычисления логарифма он "округляет" целые числа к нулю, то есть из 2 (нормальное такое 2 = 2.00000...) он делает 1. Дробную часть то он правильно найдет, спору нет. 2 DEEP А-а-а-а! Нет! Не хочу... Неужто придется...
ABCetc Не говори ерунды. Ты небось свое "нормальное такое" число в отладчике смотришь с огруглением до double, а в самом процессоре оно сидит в extended как 1.(9). Если сначала выгрузить число в double или single с обычным огруглением к ближайшему (RC = 00b), а затем загрузить заново и сделать frndint с округлением к нулю (RC = 11b), то все должно быть нормально
2 leo о... попробуем. Кстати, а логарифм по основанию 10 из 1000 - это в сопроцессоре будет 2.(9)? Если да - то нафиг такой сопроцессор нужен.
Народ может вы пользуетесь отладчиком olly с антиотладочными плугами? у меня с сопроцессором глюк из-за них был. Пока не удалил все. Пришлось 2 olly иметь, одну для программирования, одну для кряка.
ABCetc Ну ты "ваще".. Во-первых, сопроцессор считает только log2, а логи по другим основаниям получаются делением на соотв.константу log2(10) и т.п. И сам log2 считается приближенно путем разложения в ряд (за искл.тривиальных случаев x=2^n), и константы являются иррациональными и заданы приближенно до 64 бит, и соотв-но при делении\умножении осуществляется округление до 64 бит мантиссы. Откуда тут возьмется "точное" значение ? В любом случае за счет ограниченного числа разрядов и округления младшего бита может получиться разница в +-2^(-63). Поэтому не стоит уподобляться плохим танцорам, которым вечно что-то мешает, а просто зарубить себе на носу, что при фпу-вычислениях нужно учитывать возможность потери точности в младших разрядах. И соответсвенно в зависимости от задачи либо "мириться" с этой неточностью, либо округлять итоговые значения до меньшего числа разрядов (double или single) - при этом мизерные ошибки исчезают и вместо 2.(9) получается 3.0