Форум программистов, компьютерный форум, киберфорум
EvgeniyT
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

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

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

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

Типы данных 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}
Здесь мы проверяем, что числа равны не в точности, но что модуль их разности меньше некоторого маленького числа. Всегда используйте такую конструкцию при сравнении чисел с плавающей точкой.
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 3
Комментарии
  1. Старый комментарий
    Это верно для любого языка программирования. Мало того, даже вычисления на бумаге с помощью шариковой ручки подчиняются этому правилу.
    Запись от wer1 размещена 11.01.2019 в 09:46 wer1 вне форума
  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)). Другими словами, даже первая цифра результата сомнительна.
    Запись от wer1 размещена 12.01.2019 в 08:35 wer1 вне форума
 
Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru