Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

[C]Что-то не понятное с веществинными числами

274
22 декабря 2007 года
Lone Wolf
1.3K / / 26.11.2006
Собственно вот есть такая программка:
Код:
#include <stdio.h>

int main() {
  double a = 40000.7771 - 0.0001;
  double b = 40000.7781 - 0.0001;

  if(a != 40000.777)
      printf("a != 40000.777\n");
  if(b != 40000.778)
      printf("b != 40000.778\n");


  return 0;
}


Вроде все просто, но результат выполнения программы поверг меня в небольшой шок. ибо вывело:
b != 40000.778

дума лаги, проверяю чему реально равно b, и шок усиливаеться, b=40000.778

разьясните, как такое может быть?
242
23 декабря 2007 года
Оlga
2.2K / / 04.02.2006
Почитай эту темку
Помоему еще тема должна быть на форуме, но это все что нашла )).
505
23 декабря 2007 года
vAC
343 / / 28.02.2006
Да, такое может привести к шоку если не иметь общие представления чисел с плавающей точкой :)
Приведу вас еще в более шоковое состояние: например число 2.3 вообще не существует для машины :)
В инженерной записи числа используется знак, мантисса и порядок. Причем мантисса - это нормализованное число. В десятичной нотации числа раскладываются по степеням 10. Например:
1*10^0 + 5*10^(-1) = 1.5
В машине же используется двоичная и число раскладывается по степеням 2. Например:
1*2^0 + 1*2^(-1) = 1.5

Также как в десятичной нотации нельзя представить например число 1/3 в виде конечного ряда, так и некоторые числа нельзя представить в двоичной. Например в вашем случае получается следующее:
40000.7781 = 40000.778100000003
40000.7781 - 0.0001 = 40000.778000000006
40000.778 = 40000.777999999998
отсюда 40000.778 != 40000.778 :)
1.6K
23 декабря 2007 года
Vov4ick
476 / / 01.02.2007
Вообще проверку на строгое равенство не хорошо использовать с вещественными числами. Нужно её приводить к нестрогому равенству, либо проверять вхождение в диапазон, либо проверять отдельно мантису или экспоненту (см функции frexp, ldexp)
2
23 декабря 2007 года
squirL
5.6K / / 13.08.2003
Цитата: vAC


Также как в десятичной нотации нельзя представить например число 1/3 в виде конечного ряда, так и некоторые числа нельзя представить в двоичной. Например в вашем случае получается с ледующее:
40000.7781 = 40000.778100000003
40000.7781 - 0.0001 = 40000.778000000006
40000.778 = 40000.777999999998
отсюда 40000.778 != 40000.778 :)



приблизительно то же я сказал вчера автору на IRC. но вопрос в другом:
a = 40000.7771 - 0.0001;
тоже не даст 40000.777
тем не менее в этом случае - сообщение не выводится ;)

505
23 декабря 2007 года
vAC
343 / / 28.02.2006
Цитата: squirL
приблизительно то же я сказал вчера автору на IRC. но вопрос в другом:
a = 40000.7771 - 0.0001;
тоже не даст 40000.777
тем не менее в этом случае - сообщение не выводится ;)



Так и 40000.777 и (40000.7771 - 0.0001) дают одинаковый результат -
40000.777000000002, поэтому и не выводится

274
23 декабря 2007 года
Lone Wolf
1.3K / / 26.11.2006
вобщем, немного повыяснял.. делто тут вот в чем.
Цитата:

Дело в том, что при переводе десятичной дроби в двоичную систем могут возникнуть бесконечные дроби в двоичной системе счисления (не уверен, периодические или нет). А тут ещё и накладываются правила округления, и получается что мы складываем два неточных значения, а потом ещё и округляем.


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

350
25 декабря 2007 года
cheburator
589 / / 01.06.2006
Цитата: Lone Wolf
Дело в том, что при переводе десятичной дроби в двоичную систем могут возникнуть бесконечные дроби в двоичной системе счисления (не уверен, периодические или нет)


Периодические.
Понятия "рациональное число" и "иррациональное число" не зависят от системы счисления. А рациональные числа всегда представимы в виде периодической дроби (и наоборот, если число представимо периодической дробью, оно рационально).
Для работы с рациональными числами есть библиотечка в boost'е:
http://boost.org/libs/rational/index.html
Можно использовать для точного сравнения таких чисел, как ваши 40000.7781 и т. п.
А поскольку компьютер конечен, все числа в нем всегда рациональны :) так что имеет смысл подумать над использованием ее для точного сравнения всех чисел.

3
25 декабря 2007 года
Green
4.8K / / 20.01.2000
Легкая для прочтения статейка по теме:
http://sergh.pisem.net/articles/float/float.html
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог