Форум программистов, компьютерный форум, киберфорум
Наши страницы
EvgeniyT
Войти
Регистрация
Восстановить пароль
Рейтинг: 5.00. Голосов: 1.

Сравнение чисел с плавающей точкой

Запись от EvgeniyT размещена 10.01.2019 в 20:41

Нашёл интересную информацию и что бы не потерять выложу сюда. Читайте как справочник.

Типы данных double и float хранят приближённое значение числа, на столько, на сколько хватает их точности. Поэтому нужно быть аккуратным при сравнении таких чисел на равенство.

Рассмотрим такой код:
C#
1
2
3
4
5
6
7
8
9
10
11
1public static void WrongMain()
2{
3    // в бинарном виде 0.1 представляется бесконечной дробью 0.00011001100...,
4    // в типах данных float и double хранится только начало этой дроби,
5    // поэтому число 0.1 представляется с погрешностью. 
6    double x = 1.0 / 10; 
7    double sum = 0;
8    for (int i = 0; i < 10; i++)
9        sum += x;
10    Console.WriteLine(sum == 1);
11}
Кажется, что он должен вывести True, однако на самом деле выводит False.

При выполнении этих операций, погрешность накапливается, и это приводит к неверным результатам.

Для того, чтобы избежать этого, при сравнивать числа с плавающей точкой нужно с учётом погрешности, вот так:


C#
1
2
3
4
5
6
7
8
1static void RightMain()
2{
3    double x = 1.0 / 10;
4    double sum = 0;
5    for (int i = 0; i < 10; i++)
6        sum += x;
7    Console.WriteLine(Math.Abs(sum - 1) < 1e-9);
8}
Здесь мы проверяем, что числа равны не в точности, но что модуль их разности меньше некоторого маленького числа. Всегда используйте такую конструкцию при сравнении чисел с плавающей точкой.
Размещено в Без категории
Просмотров 215 Комментарии 3
Всего комментариев 3
Комментарии
  1. Старый комментарий
    Это верно для любого языка программирования. Мало того, даже вычисления на бумаге с помощью шариковой ручки подчиняются этому правилу.
    Запись от нтч размещена 11.01.2019 в 09:46 нтч вне форума
  2. Старый комментарий
    Цитата:
    Сообщение от нтч Просмотреть комментарий
    Это верно для любого языка программирования. Мало того, даже вычисления на бумаге с помощью шариковой ручки подчиняются этому правилу.
    Да, все верно. Но когда пишешь ручкой на бумаге, обычно это десятичная система счисления, где человеку сразу видны места, в которых будет ошибка округления и ее можно увидеть и учесть.
    А когда пишешь
    а = 0.1;
    b = 872782577.12544;
    c = 10.0;

    Ожидаешь, что
    a * b * c будет равно b

    и даже в голову не приходит по началу, где здесь может быть ошибка.
    Запись от Orsanka размещена 11.01.2019 в 10:07 Orsanka вне форума
  3. Старый комментарий
    Цитата:
    Сообщение от Orsanka Просмотреть комментарий
    а = 0.1;
    b = 872782577.12544;
    c = 10.0;

    Ожидаешь, что a * b * c будет равно b
    и даже в голову не приходит по началу, где здесь может быть ошибка.
    Вы тысячу раз правы. Если предположить, что число а задано приближенно с абсолютной погрешностью 0,05, то результат умножения будет ошеломителен: 900 000 000. Ведь относительная погрешность первого числа равна 50% (число находится на интервале (0,05; 0,15)). Другими словами, даже первая цифра результата сомнительна.
    Запись от нтч размещена 12.01.2019 в 08:35 нтч вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru