BratSinot писал(а): ↑16.06.2012 18:08
Хм... Осталось только придумать как сделать это максимально точно.
эх... Вы в школе не учились? Округляйте. В двоичной системе правила примитивные: если старший из отбрасываемых битов == 0, ничего не делаете. Иначе +1. Конечно это не 1, а 1/M, но это будет уже потом, когда поделите. Важно понимать, что это НЕ улучшает точность, это просто смещает математическое ожидание ошибки. Если просто отбрасывать лишнее, тогда вы _всегда_ будете уходить в минус, что плохо - например складывая 100500 раз числа, вы получите результат намного меньше истинного, если числа случайные, то математическое ожидание ошибки будет в 100500 больше, чем величина погрешности на одном шаге. Т.е. ошибки накапливаются.
BratSinot писал(а): ↑16.06.2012 18:08
Хм... Осталось только придумать как сделать это максимально точно. Потому-что как я делаю в лоб, то например число 2.4 я получаю как 2.3999998569488525390625, когда его можно представить как 2.400000095367431640625.
в данном случае есть смысл _ухудшить_ точность на 1 бит. Если вам доступен вычислитель на 31 бит (32 минус 1 бит для знака), то сделайте точность 30 бит, а 31й используйте для округления.
BratSinot писал(а): ↑16.06.2012 18:08
Хотя не, такой способ влоб не прокатит. На single-precision еще можно, т.к. там мантиса небольшая, а на double-precision мантиса уже больше, не говоря о quad-precision. Вообщем придется идти обходными путями...
нет никакой разницы, какая у вас мантисса. Разница в том, сколько вам нужно _десятичных_ цифр точности. Например если вам нужно 6 цифр, то вам понадобится множитель в 21 бит, а именно 2097152. Причём не важно, 12345.6 это или 1.23456. Для double вам очевидно потребуется множитель 18014398509481984 (2^54), и очевидно, что технически проще взять множитель 2^63 (в 64х битных системах этот тип нативный, а в 32х битных легко реализуется через 4 умножения 32х битных половинок). Это обеспечивает требуемую вами точность в 15 десятичных цифр. Больше в ваш double просто не влезет (точнее, никак не повлияют на конечный результат).
И да,
никогда не сравнивайте на точное равенство дробные числа! Они неравны ВСЕГДА. Единственное исключение - если вы используете double для хранения целых. Да и то... Впрочем Intel обещает, что до 64х бит их FPU считают точно (только сложение и умножение естественно). Потому результат 2.3999998569488525390625 ничем не хуже 2.400000095367431640625. Ну за исключением накопления погрешности.