5 / 3 / 2
Регистрация: 27.04.2022
Сообщений: 63

Точность чисел с плавающей точкой/запятой

10.05.2025, 02:32. Показов 3866. Ответов 42
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!

Имеется массив чисел типа double от 1.000 до 10.000. Каждое число задано с точность до 10^-3. Также есть метод, который принимает число и возвращает ближайшее большее к нему число из этого массива. Всё работает хорошо, кроме одного числа - 1.6, которое всегда возвращается, собственно, не как 1.6, а как 1.6000000000000003. Я понимаю, что с числами с плавающей точкой/запятой не всё так просто, как может показаться на первый взгляд, но всё-таки:
- почему это так работает? Причём только с этим числом. Все остальные возвращаются такими, какими они заданы в массиве;
- возможно ли от этого избавиться без применения округлений, обрезаний и прочих инструментов?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.05.2025, 02:32
Ответы с готовыми решениями:

Перевести десятичное число с плавающей запятой (точкой) в шестнадцатеричную систему и в 4-байтовом формате
Здравствуйте. Как перевести десятичное число с плавающей запятой (точкой) в шестнадцатиричную...

Генерация случайных чисел с плавающей точкой
Как сгенерировать случайное число на отрезке от, например, 1.2144 до 145.34213 ?

Сравнение чисел с плавающей запятой с точностью
Добрый день. Стоит задача сравнить частное двух чисел с числом Pi. Но максимальное значение...

42
 Аватар для Andrey-MSK
3390 / 2276 / 388
Регистрация: 14.08.2018
Сообщений: 7,697
Записей в блоге: 4
12.05.2025, 11:39
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от wizard41 Посмотреть сообщение
Погрешность настолько мала, что ей можно пренебречь..
С double никогда вот такое условие не выполнится, ну может быть и выполнится, но с вероятностью 0,00001%
C#
1
2
3
4
5
double v1;
double v2;
// ...
if((v2 - v1) == 0)
{ ... }
так что для расчётов, где нужна математическая точность, только decimal...
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3461 / 2782 / 575
Регистрация: 04.09.2018
Сообщений: 8,746
Записей в блоге: 3
12.05.2025, 11:43
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
С double никогда вот такое условие не выполнится
А при чем здесь это?
Я еще ранее ТСу говорил, что сравнивать даблы нужно с некоторой точностью..
0
 Аватар для Andrey-MSK
3390 / 2276 / 388
Регистрация: 14.08.2018
Сообщений: 7,697
Записей в блоге: 4
12.05.2025, 11:49
Цитата Сообщение от wizard41 Посмотреть сообщение
А при чем здесь это?
Ну фиг его знает как они тут считают...
Цитата Сообщение от wizard41 Посмотреть сообщение
Поэтому, например, в небесной механике или в астрономических расчетах (траекторий полетов, орбит) принимают всего 5-6 знаков числа ПИ - этого достаточно вполне. Погрешность настолько мала, что ей можно пренебречь..
0
152 / 136 / 29
Регистрация: 02.07.2013
Сообщений: 996
12.05.2025, 11:51
Цитата Сообщение от wizard41 Посмотреть сообщение
Поэтому, например, в небесной механике или в астрономических расчетах (траекторий полетов, орбит) принимают всего 5-6 знаков числа ПИ - этого достаточно вполне. Погрешность настолько мала, что ей можно пренебречь..
это видимо, если вручную считают, потому что иначе зачем им отказываться от зашитой в машину константы?

уточню ваше утверждение:
невозможность обеспечить высокую точность измерений и промежуточных вычислений делает бесполезным брать число пи с высокой точностью (поэтому считаем достаточной точностью). так если вы циркулем измерите диаметр круга, то нет смысла при вычислении в столбик брать пи с точностью 10 знаков после запятой, так как уже при измерениях заложена ошибка.

или, альтернативно, можно предположить, что изначально стоит задача посчитать до стольких знаков после запятой.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3461 / 2782 / 575
Регистрация: 04.09.2018
Сообщений: 8,746
Записей в блоге: 3
12.05.2025, 11:58
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
как они тут считают
Через double все прекрасно считается и достигается приемлемая точность.

Добавлено через 6 минут
golosalex, этот пример не сравнения дробных чисел, а показатель степени влияния каждого последующего знака на конечный результат. Причем здесь только 6 и 10 знаков, а ТСа волнует аж 16-й!
Смысл же всего этого таков: не нужно ничего отбрасывать и округлять. Числа должны оставаться такими, какими есть и участвовать в расчетах в неизменном виде. А уже выводить пользователю их значения можно с какой-л. точностью..
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
13.05.2025, 23:43
Цитата Сообщение от power_factor Посмотреть сообщение
- возможно ли от этого избавиться без применения округлений, обрезаний и прочих инструментов?
Для "человеческих" чисел нужно использовать тип decimal, а не double.
double - это тип для научных вычислений.
decimal - для финансово-бухгалтерских.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
14.05.2025, 01:03
Цитата Сообщение от Элд Хасп Посмотреть сообщение
decimal - для финансово-бухгалтерских
А в чем разница? Просто шире, больше точность?
Но всё та же жоППа, только вид сбоку.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
для финансово-бухгалтерских
Только спец. типы.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
14.05.2025, 01:55
Цитата Сообщение от SmallEvil Посмотреть сообщение
А в чем разница? Просто шире, больше точность?
В том что точность представления не двоичная, а десятичная. Что имеет большое значение при работе с "точными" дробными числами. Например, если копейки представлены долями рубля, то в double невозможно точно записать 0.2 рубля (то есть 20 копеек). И если таких дробных чисел много (что естественно для финнасово-бухгалтерских операций), то конечный результат будет непредсказуем. Хотя точность для таких операций должна быть "абсолютной", до одной копейки и, если нужно, долей копеек.
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
14.05.2025, 02:33
Цитата Сообщение от Элд Хасп Посмотреть сообщение
В том что точность представления не двоичная, а десятичная. Что имеет большое значение при работе с "точными" дробными числами.
Понятно. Спасибо.
1
152 / 136 / 29
Регистрация: 02.07.2013
Сообщений: 996
14.05.2025, 08:07
Цитата Сообщение от Элд Хасп Посмотреть сообщение
В том что точность представления не двоичная, а десятичная. Что имеет большое значение при работе с "точными" дробными числами. Например, если копейки представлены долями рубля, то в double невозможно точно записать 0.2 рубля (то есть 20 копеек). И если таких дробных чисел много (что естественно для финнасово-бухгалтерских операций), то конечный результат будет непредсказуем. Хотя точность для таких операций должна быть "абсолютной", до одной копейки и, если нужно, долей копеек.

чет я не силен в бух учете, но никогда не сталкивался с переводами долей копеек, а значит полагаю, что их скорее всего округляют. а если все в копейках считается, то не проще ли как-то все в интах делать? ну или в даблах если на то пошло с округлением в конце. как - то можете обосновать, что погрешность может накопиться достаточной, чтобы обратить на себя внимание. вот в мат расчетах такие проблемы бывают и то вполне обходятся даблами. а тут то нафиг оно? и все равно с децимал подозреваю будет не всегда все гладко и какая-то потеря точности да случается. там же тоже мантиса степень и знак как в дабле?

но вполне допускаю что заблуждаюсь, могу изменить мнение под общественным давлением))))
0
 Аватар для Andrey-MSK
3390 / 2276 / 388
Регистрация: 14.08.2018
Сообщений: 7,697
Записей в блоге: 4
14.05.2025, 09:23
SmallEvil, golosalex, Тип decimal хранится в памяти как целое число с индексом разряда. Все операции с ним производятся как с целым числом, потому и нет ошибок, которые присущи типам double и float так как невозможно в памяти ПК воспроизвести точно число с плавающей точкой.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
14.05.2025, 11:30
Цитата Сообщение от golosalex Посмотреть сообщение
чет я не силен в бух учете, но никогда не сталкивался с переводами долей копеек, а значит полагаю, что их скорее всего округляют.
Доли копеек в основном возникают при расчёте каких-то калькуляций.
Да потом они по итогу округляются. Но проведение вычислений в научной системе, потом округление в ней и приведение к десятичному виду часто может дать не тот результата, если всё это делать сразу в десятичном формате.
А одно из главных требований к финансово-бухгалтерским операциям - это возможно их точного повторения различными методами. Это нужно для проведение сверок и контролей.
double может дать разный результат даже при простом суммировании массива значений в зависимости от порядка их добавления в сумму.

Добавлено через 2 минуты
Простейшее правило арифметики A+B+С=C+B+A в реальности для double значений будет не всегда выполняться.

Добавлено через 1 минуту
P.S. Добро пожаловать в вычислительную математику!

Она не всегда совпадает со "школьной" математикой.
0
152 / 136 / 29
Регистрация: 02.07.2013
Сообщений: 996
14.05.2025, 12:20
попробую уточнить свою позицию:

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Тип decimal хранится в памяти как целое число с индексом разряда. Все операции с ним производятся как с целым числом, потому и нет ошибок, которые присущи типам double и float так как невозможно в памяти ПК воспроизвести точно число с плавающей точкой.
так очень похоже на то же что и float. в обоих случаях есть мантиса (целое число) степень (насколько сдвинуть десятичный разделитель) и один бит на знак.

если вы уверены что есть принципиальная разница в вычислениях, то вот пример ниже

C#
1
2
3
4
        decimal a = 1;
        decimal b = a / 3;
        decimal c = b * 7;
        decimal d = c * 3;
почему тогда d не будет в итоге точно равно семи?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
А одно из главных требований к финансово-бухгалтерским операциям - это возможно их точного повторения различными методами. Это нужно для проведения сверок и контролей.
вообще если есть такие требования от бухгалтерии, то очевидно так и надо делать. но все равно это выглядит как следование правилу "так заведено".

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Простейшее правило арифметики A+B+С=C+B+A в реальности для double значений будет не всегда выполняться.
так и для decimal тоже, вот пример выше.


единственное оправдание что я могу придумать - это то что какой-то годовой ввп мира с точностью до цента может не влезть, потому что точность будет примерно 15 знаков. но есть же какой-то условный long...

вот потому и подозреваю, что такая явно избыточная точность выглядит странной. (ну или просто у меня мало денег чтобы из в decimal хранить...)
0
 Аватар для Andrey-MSK
3390 / 2276 / 388
Регистрация: 14.08.2018
Сообщений: 7,697
Записей в блоге: 4
14.05.2025, 12:25
Цитата Сообщение от golosalex Посмотреть сообщение
так очень похоже на то же что и float. в обоих случаях есть мантиса (целое число) степень (насколько сдвинуть десятичный разделитель) и один бит на знак.
Вот почитайте - Decimal floating point in .NET.

Добавлено через 2 минуты
Как в памяти компьютера представлен тип данных decimal?
1
152 / 136 / 29
Регистрация: 02.07.2013
Сообщений: 996
14.05.2025, 12:47
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Вот почитайте - Decimal floating point in .NET.
Добавлено через 2 минуты
Как в памяти компьютера представлен тип данных decimal?
о как! основание для степени тут 10 а не два. тогда понятно разница есть. сразу бы на это внимание обращали когда про decimal говорят, а то как будто это точный клон float с расширенным диапазоном.

вторую ссылку я находил, но не особо вникая решил, что в формуле 10 - это в двоичной системе))

Добавлено через 2 минуты
иногда очень бы хотелось чтобы весь диапазон double покрывался decimal, а тут оказывается проблема более сложная.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
14.05.2025, 13:53
Цитата Сообщение от golosalex Посмотреть сообщение
и все равно с децимал подозреваю будет не всегда все гладко и какая-то потеря точности да случается
value/5
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
0.00000000000010000
0.00000000000002000
0.00000000000000400
0.00000000000000080
0.00000000000000016
0.000000000000000032
0.0000000000000000064
0.00000000000000000128
0.000000000000000000256
0.0000000000000000000512
0.00000000000000000001024
0.000000000000000000002048
0.0000000000000000000004096
0.00000000000000000000008192
0.000000000000000000000016384
0.0000000000000000000000032768
0.0000000000000000000000006554
0.0000000000000000000000001311
0.0000000000000000000000000262
0.0000000000000000000000000052
0.000000000000000000000000001
0.0000000000000000000000000002
Но она случится по вполне естественным причинам, а не по причине погрешности представления чисел как у типов c плавающей точкой.

Нужен такой тип в С++.
А то новичкам совсем туго приходится.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
14.05.2025, 14:06
Цитата Сообщение от golosalex Посмотреть сообщение
так очень похоже на то же что и float. в обоих случаях есть мантиса (целое число) степень (насколько сдвинуть десятичный разделитель) и один бит на знак.
Нет.
float и double имеют двоичные мантиссу меньше 1 и экспоненту. Поэтому у них не "десятичная" точка, а "двоичная".
decimal же имеет целую мантиссу и десятичную экспоненту. Поэтому у него действительно десятичная точка.

Цитата Сообщение от golosalex Посмотреть сообщение
так и для decimal тоже, вот пример выше.
Да. decimal тоже не даёт гарантии точности. Но ошибка в decimal такая же как при любых других способах вычисления: таблицы, калькулятор, счёты, различные CRM-ERP и др.
Всюду с decimal обращаются по правилам банальной школьной арифметики и всюду получат один и тот же результат.
Одно то что не всякое десятичное конечное нецелое число можно представить конечным двоичным числом - накладывает серьёзные ограничения на их использование в финансах.

Вот пример:
C#
1
2
3
4
5
      double a = 5;
      double b = 1;
      decimal a1 = 5;
      decimal b1 = 1;
    Console.WriteLine("{0:G17}\t{1:G17}", b/a, b1/a1);
Code
1
0.20000000000000001     0.2
Добавлено через 1 минуту
Цитата Сообщение от golosalex Посмотреть сообщение
о как! основание для степени тут 10 а не два.
Пока писал своё сообщение (отвлекали по работе) - оказывается уже ответили.
1
152 / 136 / 29
Регистрация: 02.07.2013
Сообщений: 996
14.05.2025, 14:59
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Пока писал своё сообщение (отвлекали по работе) - оказывается уже ответили.
благодарю за пояснение, всегда приятно узнать что-то новое. я какое-то время назад пытался разобраться как на низком уровне хранится децимал, но толи в глаза не бросилось, то ли вообще умалчивается отличие от double.
0
 Аватар для Andrey-MSK
3390 / 2276 / 388
Регистрация: 14.08.2018
Сообщений: 7,697
Записей в блоге: 4
14.05.2025, 15:17
Один раз попался сайт где можно было увидеть как хранятся числа разных типов в памяти. Дак вот, если ввести double/float и потыркать кнопку обновить, то каждый раз получалось разное число в двоичной системе, а целые и decimal/numeric всегда одинаково выглядели
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
14.05.2025, 15:46
Цитата Сообщение от golosalex Посмотреть сообщение
как на низком уровне хранится децимал
У Intel процессоров есть поддержка в FPU десятичной арифметики. Десятичное число представляется 10 байтами.
Но вроде только целые десятичные. Не помню точно сейчас.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.05.2025, 15:46

Хранение чисел с плавающей запятой в памяти
Здравствуйте. Скорее, вопрос не по теме, просто не знаю, куда задать вопрос. Вопрос связан с...

Формат представления чисел с плавающей запятой
Передаю число с плавающей запятой через COM на МК 0,0043 но в итоге получаю на самом МК число...

число с плавающей точкой
подскажите как из строкого формата числа с двумя числами после запитой, например 122,00 или 32,94,...

Числа с плавающей точкой
Как отделить целую часть и дробную? Например имеем число 12.54 число 12 должно бить записано в...

Введение данных с плавающей точкой в TextBox
Такая проблема: на форме есть 2 текстбокса, в один должно вводится число, которое будем приводить к...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

Новые блоги и статьи
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru