![]() |
|
![]() ![]() ![]() |
|
Wowa |
|
|||
Эксперт ![]() Профиль Группа: Админ Сообщений: 15017 Регистрация: 14.9.2000 Где: Винград Репутация: нет Всего: 290 |
Создал я значит цикл:
for ($i = 7.12; $i <= 10; $i=$i+0.01) { ... } При его выполнении выясняется, что компьютер прибавляет к $i 0.01 при каждом проходе цикла, но иногда компьюет прибавляет не 0.01, а меньшее число. У меня на компьютере комп досчитал до: $i=9.51 и следуюшее значение выдало $i=9.5199999999999 Далее: 9.5299999999999 9.5399999999999 .... С чем это связано, как объясняется и как с этим бороться? |
|||
|
||||
Wowa |
|
|||
Эксперт ![]() Профиль Группа: Админ Сообщений: 15017 Регистрация: 14.9.2000 Где: Винград Репутация: нет Всего: 290 |
Запусти я этот код на другом компьютере - результат такой же.
|
|||
|
||||
cardinal |
|
||||||
![]() Инженер ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 6003 Регистрация: 26.3.2002 Где: Германия Репутация: 5 Всего: 99 |
Компьютер не ошибается в этом случае, что подтверждает тот факт, что как ты сам сказал второй компер ведет себя точно также.
С бинарной арифметикой.
Объясняется тем, что бинарный система счисления не позволяет выражать дроби. Был бы я в Си, я бы сделал листинг на asm и тогда делал бы последующие выводы, т.к. не уверен чем реализована работа с дробными числами - предполагаю, что этим занимается coprocessor. Но все равно вопрос остается, что с твоим кодом делает compiler.
Если это такой одиночный случай в проге, то я бы сделал так: for (i = 712; i <= 1000; i++) { ... } ну и в момент надобности делал бы операцию div 100 и mod 100 получая таким образом целую часть и дробную. А если это не одиночный случай, то я бы сделал тоже самое несколько раз потому, что ничего более полезного в голову не приходит. ![]() p.s. Уже даже Admin нарушает правила форума! Аж три вопроса в раз: "с чем связано?", "как объясняется?" и "как с этим бороться?". ![]() -------------------- Немецкая оппозиция потребовала упростить натурализацию иммигрантов В моем блоге: Разные истории из жизни в Германии "Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино". А. и Б. Стругацкие |
||||||
|
|||||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 33 Всего: 110 |
бинарная система кроме основания ничем не отличается от десятичной и позволяет выражать дроби причина в том, что одни и теже дроби в одной системе могут иметь простой вид, а в другой становиться периодическими а периодические дроби компьютер усекает (независимо от того, как там реализована арифметика) -------------------- qqq |
|||
|
||||
Wowa |
|
|||
Эксперт ![]() Профиль Группа: Админ Сообщений: 15017 Регистрация: 14.9.2000 Где: Винград Репутация: нет Всего: 290 |
Я сделал цикл:
for ($k = 712; $k <= 1000; $k++) { $i=$k/100; ... } Теперь похоже все Ок. Вычисляется все точно. |
|||
|
||||
val |
|
|||
![]() Program developer ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 992 Регистрация: 14.1.2003 Где: г. Киев Репутация: 1 Всего: 7 |
Да, эта тема обсуждалась в рубрике С/С++, действительно двоичная арифметика имеет такие ньансы при работе с действительными числами:
-------------------- Терпимость - величайшее благо человечества... Ярчайший признак интеллекта – постоянно хорошее настроение… |
|||
|
||||
OlegsDP |
|
|||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 25.2.2004 Репутация: нет Всего: 1 |
Можно побаловаться с таким myprog.cpp:
Это сообщение отредактировал(а) OlegsDP - 25.2.2004, 14:28 |
|||
|
||||
Waters |
|
|||
Новичок Профиль Группа: Участник Сообщений: 28 Регистрация: 16.11.2003 Репутация: нет Всего: нет |
И в чем смысл "баловства"?
![]() |
|||
|
||||
OlegsDP |
|
|||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 25.2.2004 Репутация: нет Всего: 1 |
Можно найти такие два числа, которые "не складываются":
myprog 1 0.000000000000001 AGA! т.е. "сложились" myprog 1 0.0000000000000001 OGO! т.е. "не сложились" |
|||
|
||||
PILOT |
|
|||
![]() производство ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2724 Регистрация: 4.4.2002 Где: москва Репутация: нет Всего: 54 |
Это связано именно с двоичной арифметикой, хотя если быть точнее то с представлением float...
число float в простом случае (я уменьшил число байт для простоты) имеет формат: SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM где: S - это знак E - Экспонента (-127...+128) M - 24бита Мантиссы (на самом деле 23) И число представляется в виде: ±mantissa × 2^exponent Например число: -12.5 будет представлено в виде: 0xC1480000. Как так получилось? Разбираемся: формат числа: SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM в двоичном коде: 11000001 01001000 00000000 00000000 шестнадцатиричный код: 00 00 48 C1 Знак = 1 следовательно это отриц. число. Значение Экспоненты 10000010b или 130d. Вычитаем 127 (это наше смещение нуля) из 130 получаем 3, это и есть Экспонента. Видно, что Мантисса выражается числом: 10010000000000000000000b считается, что перед мантиссой всегда есть единица, в этоге получаем следующее число в двоичном представлении: 1.10010000000000000000000b Теперь учитываем экспоненту, т.к. она равна трем, то точка сдвинется на три разряда вправо: 1100.10000000000000000000b это число и есть двоичное представление -12.5. Проверяем (целая часть): (1 × 2^3) + (1 × 2^2) + (0 × 2^1) + (0 × 2^0)=12 (учитвая знак: -12) теперь дробная часть: 10000000000000000000b (1 × 2^-1) + (0 × 2^-2) + (0 × 2^-3) + … = 0.5 прибавляем: -(12+0.5)=-12.5 теперь не трудно сообразить, что 0.01 представляется сложнее в мантиссе, чем -12.5, потому что 0.01 это не .0625 или .125. А для представления 0.01 придется использовать все биты мантиссы (т.е. точности не хватит), так или иначе набежит один значащий бит в мантиссе, либо в плюс либо в минус. СУВ. -------------------- тут могла быть Ваша реклама... |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Алгоритмы" | |
|
Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Алгоритмы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |