|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
|
Каков принцип округления дробных чисел у компьютера/компилятора?25.07.2018, 23:01. Показов 7511. Ответов 88
Метки нет (Все метки)
Всем привет.
У меня тут такой вопрос для темы: Как именно осуществляется округление дробных чисел в компьютере? Какими правилами он пользуется? Я пишу программу, просто как тренировочную, в целях практики, так как я только начинаю путь программирования,ее цель (программы) это тренинг по математике, различного уровня сложности и головоломки, и вот в этой программе, возникли проблемы с расхождением результатов: результат, который ввожу я, (вычисленный на калькуляторе) отличается от результата, который вычисляет компьютер. При том что используемый калькулятор - стандартный в ОС Windows. Мало того значение в переменной округляется на разных этапах компиляции, что приводит в расхождению результатов и невозможно подобрать правильный. Такое ощущение, что компьютер играет со мной в стаканчики и крутит вертит эти результаты, чтобы запутать. Прогонял через отладчик, и даже просто переписывал результат из переменной хранящей результат, но при сравнении снова выдает ошибку совпадения, результаты разные, компилятор округлил значение на каком то этапе компиляции и уже несовпадение. В общем вопрос очень тонкий, надеюсь есть решения, которые можно осуществить на уровне начальных знаний о С++, или же надо подключать сложные и громоздкие математические библиотеки, с которыми я еще не знаком? Конечно программа не принесет прибыли, и даже может пользы (в плане математики) от нее будет не много, но как практическая работа она очень интересная. P.S. Пытался загрузить проект (правда он не закончен), но не получается пока... буду пытаться еще грузить, может кому интересно будет на него взглянуть.
0
|
|
| 25.07.2018, 23:01 | |
|
Ответы с готовыми решениями:
88
Как избежать округления дробных чисел Как избежать округления дробных чисел Каков принцип работы атрибутов |
|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
|
| 25.07.2018, 23:34 [ТС] | |
|
Загрузился только .cpp файл, весь проект почему то не грузиться.
0
|
|
|
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
|
||
| 25.07.2018, 23:55 | ||
|
Впрочем, если вы о преобразовании double->int, то там просто обрубается дробная часть.
2
|
||
|
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
|
||
| 26.07.2018, 00:17 | ||
|
txtbit, думаю, что в калькуляторе Windows используется длинная арифметика.
1
|
||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|||
| 26.07.2018, 00:19 | |||
|
А по поводу чисел с плавающей точкой - да, там степень хранится для 2ки (в двоичной системе процессору легче считать), поэтому они изначально задаются не равными задаваемым десятичным дробям.
1
|
|||
|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
|
| 26.07.2018, 11:04 [ТС] | |
|
Всем спасибо за ответы, но видимо я не совсем точно выразил суть своего вопроса. Слишком мало конкретики в моем изложении сути, поэтому прогнал программу через отладчик и записал изменения всех вычислений на разных этапах, для облегчения более детального и главное визуального восприятия вопроса. Вписывать сюда примеры не стал будет очень много непонятных моментов, поэтому просто вложил файл с таблицей, где наглядно видно в чем заключается суть вопроса этой темы, и надеюсь есть ей решения...
Заранее всем спасибо.
0
|
|
|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
||
| 26.07.2018, 11:21 [ТС] | ||
|
0
|
||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|
| 26.07.2018, 11:37 | |
|
txtbit, выводишь через cout ? Если да, то укажи сколько тебе требуется дробных знаков с помощью std::setprecision
https://en.cppreference.com/w/... tprecision Если требуется большая точность, чем у double, то возьми например компилятор minGW, и используй тип long double (https://en.wikipedia.org/wiki/Long_double), т.к. компиляторы от microsoft работают с ним аналогично double.
0
|
|
|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
|||
| 26.07.2018, 11:56 [ТС] | |||
|
Добавлено через 2 минуты Сейчас перепроверял свои данные и у меня сомнения, что в первом примере я допустил ошибку в записи чисел, и написал неверное число, что привело в результате к расхождению результатов, но второй вариант точно составлен очень правильно, это проверено.
0
|
|||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|||
| 26.07.2018, 12:04 | |||
Сообщение было отмечено txtbit как решение
РешениеДобавлено через 4 минуты https://ru.wikipedia.org/wiki/... й_точности https://www.cyberforum.ru/blogs/18334/blog88.html
0
|
|||
|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
||
| 26.07.2018, 19:56 [ТС] | ||
|
0
|
||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
||
| 26.07.2018, 20:04 | ||
|
Т.е. что будет округлено при переводе из твоих введённых чисел из нормированных по основанию 10 на нормированные с основанием 2, какие остатки будут отброшены при делении полученных чисел в формате double и т.д. В общем проведи вычисления так, как проводит их процессор. Учитывая что целые значения процессор умеет считать точно, если они не переполняются.
0
|
||
|
Модератор
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
|
||
| 26.07.2018, 20:08 | ||
|
txtbit, посмотри вот этот блог
https://www.cyberforum.ru/blogs/18334/blog88.html Evg все доступно описал Добавлено через 1 минуту впрочем TRam_, уже дал на него ссылку ![]() Добавлено через 3 минуты пойми что в компьютере данные хранятся в двоичном виде а std::setprecision выдает десятичный вид так если введешь 0.1 то никогда не получишь этого значения поскольку 0.1 бесконечная дробь в двоичном представлении
0
|
||
|
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
|
||
| 26.07.2018, 20:11 | ||
|
0
|
||
|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
||||
| 26.07.2018, 20:44 [ТС] | ||||
|
Добавлено через 2 минуты Добавлено через 6 минут
0
|
||||
|
Модератор
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
|
||
| 26.07.2018, 20:49 | ||
|
вот здесь подробней setprecision() и setiosflags() а вот cout,без специальных флагов, выдает десятичный вид
0
|
||
|
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
|
|
| 26.07.2018, 20:58 [ТС] | |
|
Вот пример записи, хранения и вывода данных типа float (использую этот тип, как "тип" переменных), из конкретных примеров во время отладки программы.
-8.40939720е-06 данные хранимые в переменной "ResultLDN", которые вычислил процессор -8.409397335238171е-6 данные вычисленные калькулятором Windows 8.4094е-06 данные, хранящиеся в переменной "ResultLDN", выведенные в консоль с помощью "std::cout".
0
|
|
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
||||||
| 26.07.2018, 21:08 | ||||||
|
Выведи
0
|
||||||
|
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
|
||
| 26.07.2018, 21:09 | ||
|
Впрочем, если вам хочется поковыряться в матане, то можете заменить столбик на модулярную арифметику. Сразу предупреждаю - деление там является очень нетривиальной операцией (зато, сложение/вычитание/умножение очень быстрое).
0
|
||
|
|
||
| 26.07.2018, 21:35 | ||
Сообщение было отмечено ValeryS как решение
Решение
Чисто на всякий случай. Нужно чётко понимать, что "число" и "запись числа" - это несколько разные вещи
Далее при печати это число (запись числа в двоичной форме записи) конвертируется в десятичную форму записи. В общем случае десятичная форма записи будет иметь очень большое число знаков после запятой В ДЕСЯТИЧНОМ ВИДЕ, несмотря на то, что в двоичном виде число знаков после запятой совсем небольшое В итоге "-8.40939720е-06" - это НЕ данные, хранимые в переменной "ResultLDN". Это их отображение в десятичном представлении, напечатанное с точностью до 8 десятичных знаков мантиссы после запятой Ну и так, чтобы наглядно всё было перед глазами. Может быть, сообразишь, почему в разных программах на экран печатаются немного разные значения C++ #include <iostream> #include <iomanip> // Число 1/3 в двоичной записи имеет бесконечное число // знаков после запятой. Хранимое в двоичном виде число по сути дела // округляется до скольких-то двоичных знаков. Чем шире тип, тем больше // двоичных знаков после запятой, т.е. тем более точно хранимое значение // будет приближено в реальному значению 1/3, но никогда его не достигнет float f = 1.0f / 3.0f; double d = 1.0 / 3.0; long double ld = 1.0L / 3.0L; int main () { // Неточно представленное в двоичном представлении число 1/3 // конвертируется в десятичную запись. При этом в десятичной записи // печатаются только первые несколько знаков после запятой. Чем // больше знаков печатается, тем ближе напечатанное значение // к реально хранимому в переменной значению (которое само по // себе НЕ является точным) // // Можем заметить, что печать как бы одного и того же значения // начиная с некоторой точности выглядит по разному для разных // типов. Это обусловлено разными потерями точности именно // в процессе хранения. Если же мы возьмём число не 1/3, а 1/2, // то там таких различий не будет, поскольку 1/2 представляется // без потерь в двоичном виде. А при преобразовании в десятичную // форму записи имеет маленькое количество десятичных знаков // после запятой. Если возьмём число 1/65536, то различия увидим // только до нескольких знаков после запятой, а дальше результаты будут // совпадать. Это обусловлено тем, что значение в двоичном виде точное, // и при преобразовании в десятичную запись имеется сравнительно // небольшое количество знаков после запятой std::cout << std::setprecision (3) << f << std::endl; std::cout << std::setprecision (6) << f << std::endl; std::cout << std::setprecision (12) << f << std::endl; std::cout << std::setprecision (20) << f << std::endl; std::cout << std::setprecision (30) << f << std::endl; std::cout << std::endl; std::cout << std::setprecision (3) << d << std::endl; std::cout << std::setprecision (6) << d << std::endl; std::cout << std::setprecision (12) << d << std::endl; std::cout << std::setprecision (20) << d << std::endl; std::cout << std::setprecision (30) << d << std::endl; std::cout << std::endl; std::cout << std::setprecision (3) << ld << std::endl; std::cout << std::setprecision (6) << ld << std::endl; std::cout << std::setprecision (12) << ld << std::endl; std::cout << std::setprecision (20) << ld << std::endl; std::cout << std::setprecision (30) << ld << std::endl; } Code 0.333 0.333333 0.333333343267 0.3333333432674407959 0.3333333432674407958984375 0.333 0.333333 0.333333333333 0.33333333333333331483 0.333333333333333314829616256247 0.333 0.333333 0.333333333333 0.33333333333333333334 0.333333333333333333342368351437
0
|
||
| 26.07.2018, 21:35 | |
|
Помогаю со студенческими работами здесь
20
Каков принцип работы парсера? Aspnet_regsql: каков принцип работы GZipstream - каков принцип многопоточного сжатия/распаковки? Каков принцип работы клиент-серверного приложения Каков принцип работы самого простого web crawler? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта
Симптом:
После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
|
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|