Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.62/34: Рейтинг темы: голосов - 34, средняя оценка - 4.62
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84

Каков принцип округления дробных чисел у компьютера/компилятора?

25.07.2018, 23:01. Показов 8782. Ответов 88
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет.

У меня тут такой вопрос для темы: Как именно осуществляется округление дробных чисел в компьютере? Какими правилами он пользуется?
Я пишу программу, просто как тренировочную, в целях практики, так как я только начинаю путь программирования,ее цель (программы) это тренинг по математике, различного уровня сложности и головоломки, и вот в этой программе, возникли проблемы с расхождением результатов: результат, который ввожу я, (вычисленный на калькуляторе) отличается от результата, который вычисляет компьютер. При том что используемый калькулятор - стандартный в ОС Windows. Мало того значение в переменной округляется на разных этапах компиляции, что приводит в расхождению результатов и невозможно подобрать правильный. Такое ощущение, что компьютер играет со мной в стаканчики и крутит вертит эти результаты, чтобы запутать.

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

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

Конечно программа не принесет прибыли, и даже может пользы (в плане математики) от нее будет не много, но как практическая работа она очень интересная.


P.S. Пытался загрузить проект (правда он не закончен), но не получается пока... буду пытаться еще грузить, может кому интересно будет на него взглянуть.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
25.07.2018, 23:01
Ответы с готовыми решениями:

Как избежать округления дробных чисел
как сделать что бы не округляло ??? float t; float z,m; using namespace std; void main(void) { m=-pow(5,2)/2;

Как избежать округления дробных чисел
не виводит дробь а только целие числа. где проблема ? #include <iostream.h> #include <math.h> int mat(double x,double...

Каков принцип работы атрибутов
Всем доброго времени суток. Объясните пожалуйста принцип работы атрибутов. То есть я написал атрибут и теперь я могу сериализовать...

88
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
28.07.2018, 20:56  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Renji Посмотреть сообщение
Не пользоваться экспоненциальной записью с десятичным порядком величин. Числа обрабатываются в форме мантисса*2^экспонента? Вот в таком формате их и вводите.
Тут еще такой момент есть, что не все числа с плавающей запятой компилятор представляет в форме мантисса*2^экспонента, некоторые из них представлены в виде экспоненциальной записи с десятичным порядком величин. И вот когда именно тот, а когда другой вид записи, не угадаешь... нет, в принципе это не важно, можно использовать хоть 1000 попыток вводить результат, ограничений нет, т.е. попробовать в виде экспоненциальной записи с десятичным порядком величин, и если не получается, то в форме мантисса*2^экспонента, но сам факт, что нет точных представлений в какой форме будет идти запись.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
28.07.2018, 20:58
Цитата Сообщение от Evg Посмотреть сообщение
А... ты про это... Просто фраза "повторение рассчёта .... не всегда воспроизводимо" по моим понятиям означает немного другое. Т.е. тут вопрос неточной формулировки
Я не претендую на точность. Там где эта фраза звучала есть формулы:
Цитата Сообщение от IGPIGP Посмотреть сообщение
Однако повторение расчёта на одной и той же системе всегда воспоизводит один и тот же результат. А вот повторение расчёта в математическом смысле не всегда воспроизводимо. То есть a+b+c != a+c+b .
и они вместе с текстом на который я дал ссылку вполне однозначно передают смысл сказанного. Результат расчёта математически эквивалентных выражений на цифровых системах не воспроизводим при применении правил средней школы (от перемены мест слагаемых сумма не меняется). Это приводит к кажущимся парадоксам вида
b = c+d
a = d+c
a != b
А выражение
abs(a-b)<eps
решает и данную проблему. Только это не для детсадовских деток. Пусть голубей гоняют. Им еще хватит на их веку.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
28.07.2018, 21:02
Цитата Сообщение от txtbit Посмотреть сообщение
Тут еще такой момент есть, что не все числа с плавающей запятой компилятор представляет в форме мантисса*2^экспонента, некоторые из них представлены в виде экспоненциальной записи с десятичным порядком величин.
Причем тут компилятор? Вам самому придется писать наколеночное преобразование в/из текстового представления с двоичным порядком величин. А процессор работает именно с двоичным порядком и никак иначе. Экзотику типа музейных экспонатов начала прошлого века и уникальных военных разработок в расчет не берем.
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,878
28.07.2018, 21:27
Цитата Сообщение от txtbit Посмотреть сообщение
Тут еще такой момент есть, что не все числа с плавающей запятой компилятор представляет в форме мантисса*2^экспонента,
все
внутри компьютера все данные хранятся в двоичном виде! для удобства чтения человеком данные могут представляться в шестнадцатеричном виде(Си не поддерживает двоичный формат) двоичные в шестнадцатеричные и наоборот преобразуются без потерь
0
-2 / 1 / 0
Регистрация: 18.07.2018
Сообщений: 84
28.07.2018, 22:11  [ТС]
Буду пробовать решить данную задачу исходя из предоставленных Вами справок и информации. О результатах и о спорных моментах буду докладывать. Вопросы еще есть конечно, но далее попробую сам покопаться в этом, учиться то надо мне, значит и пытаться тоже мне. Всем
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
28.07.2018, 22:48
Цитата Сообщение от txtbit Посмотреть сообщение
Всем
И Вам
Посмотрите кстати программку aneasycalc. Она, при включённом "Интеллектуальном алгоритме" будет давать всегда один и тот же результат при любых математически тождественных выражениях, независимо от порядка операций в записи. Дети будут довольны. И поскольку дети - святое дело, обещаю вам ключ к полной версии в подарок.
Удачи!
0
0 / 0 / 0
Регистрация: 27.11.2017
Сообщений: 22
28.07.2018, 23:44
Цитата Сообщение от txtbit Посмотреть сообщение
Если можно тут по подробнее... Если не сложно, хоть самый маленький пример, пусть даже не полный, только на С++, а то я синтаксис других языков не понимаю, пока что.....
Ну к примеру у вас все числа имеют до 10 цифр после запятой, а те данные что вводит пользователь лишь 5. Значит вам нужно "обрезать" значения, которые рассчитывает программа.
предположим расчёт идет в 2 формулы.
1) обрезаете входные данные до первой формулы, чтобы кол-во знаков не превышало 5, потом проводите расчет по 1 формуле
2) обрезаете результат первой формулы также до 5 знаков и проводите расчёт по 2 формуле
3) обрезаете конечный результат и потом уже сравниваете для дальнейших действий.

Если у вас черти сколько формул, то чтобы каждый раз не писать эту формулу округления / откидывания сделайте функцию
C++
1
2
3
double func (double cheslo){
     return round(cheslo*100000)/100000;
}
а в самой программе прогоняете входные переменные и результаты расчета через свою функцию.
написал 1 формулу, для наглядности
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Int main(){
  double a,b,c, user, res;
 
  a=23.424121;22402
  b=14.1515323410042
  c= 4124.1241512
 
  a=func(a);
  b=func(b);
  c=func(c);
 
  res=func( (a*b*c)/(c+a));
  
  cout<<"Введите свой результат (до 5 знаков после зпт)\n>";
  cin>>user;
 
  if res == user then
    {
    cout<<"Верно\n"}
  else
    {cout<<"Расёт неверен!\n"}
  end if
}
p.s. лучше, чем это сделали я вряд ли смог,поэтому советую просто в поисковике вбить округление в си. Там наглядно распишут о 4 функциях, три из них округляют и 1 просто откидывает все цифры после запятой.

Добавлено через 4 минуты
Если это то, что вам нужно, то можете добавить точность расчета, чтобы пользователь сам выбирал сколько знаков после запятой должно быть, конечно, в меру возможности аппаратуры и по.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
29.07.2018, 10:52
Цитата Сообщение от SemenTVS Посмотреть сообщение
Ну к примеру у вас все числа имеют до 10 цифр после запятой, а те данные что вводит пользователь лишь 5. Значит вам нужно "обрезать" значения, которые рассчитывает программа.
Возьмём два простых и наглядных числа с 5-ю знаками после запятой и перемножим:
https://www.cyberforum.ru/cgi-bin/latex.cgi?IgnorantResult =0,12345\cdot 0,12345
получим:
0,0152399025
тут 10 знаков. Вы предлагаете оставить 5 ?
0,01523
И правда, - подумаешь, "почти" 0,00001 разница. Неважно, что она в результате округления попала в 5-й "разрешённый" разряд. Важно именно то, что потеряно 5 знаков: 0,0000099025
-не больше ни меньше.
SemenTVS, я спрашивал вас, что значит "округлять в процессе вычисления".
https://www.cyberforum.ru/post12567064.html
Вы не ответили тогда. Скажите, этот ваш последний пост можно считать ответом? Если да, - можете не отвечать. В знак согласия.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
29.07.2018, 11:25
Цитата Сообщение от ValeryS Посмотреть сообщение
есть старый способ округления
А при делении на сто разве оно не может потерять точность?
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,878
29.07.2018, 11:55
Цитата Сообщение от nmcf Посмотреть сообщение
разве оно не может потерять точность?
может и не может
все зависит от задачи
точность понятие абстрактное она бывает абсолютная и относительная
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21287 / 8312 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
29.07.2018, 12:12
Цитата Сообщение от nmcf Посмотреть сообщение
А при делении на сто разве оно не может потерять точность?
Даже если взять вещественное число, которое не имеет дробной части, потом умножить его на 100 и поделить на 100, то даже здесь могут случиться потери при больших начальных значениях. Поэтому подобные эрзац-методы годны только для школьников на ранних периодах обучения при решении определённого класса школьных задач. Чтобы изначально не забивать голову сложными вещами об устройстве плавающих чисел, тем более всё равно не поймут
2
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
29.07.2018, 12:55
Evg, а как правильно-то?
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,878
29.07.2018, 13:25
Цитата Сообщение от Evg Посмотреть сообщение
Даже если взять вещественное число, которое не имеет дробной части,
даже если взять целое число переполнение однако
вот например
C++
1
2
3
unsigned char a=10;
a*=100;  //0xE8= 232
a/=100;// 2
и это переполнение не только в программировании
например раньше были электрические счетчики с тремя разрядами, потом надзорные органы сильно удивлялись , как так нажгли 1Квт за месяц
Цитата Сообщение от Evg Посмотреть сообщение
Поэтому подобные эрзац-методы годны только для школьников
это не эрзац, сиречь заменитель, а вполне себе прикладные методы,для каждой задачи свой
этак и логарифмическую линейку можно эрзацем назвать
Другое дело что в абсолют их вводить не стоит
еще раз процитирую "Иду на грозу" Д. Гранина
На втором курсе они вместе делали лабораторные работы по электрическому разряду.

— Давай поставим электроды под углом, — предложил Тулин.

Им было скучно выполнять то же самое, что делали на соседних столах, и то, что делали здесь из года в год поколения второкурсников. Они поставили электроды под углом, кроме того, они обмакнули их в чернила. Результаты получились странные, не сходящиеся с формулой. Преподаватель сказал, что, очевидно, для таких условий формула неверна. Он не видел в этом ничего особенного, но Крылов и Тулин были потрясены. Впервые они столкнулись с тем, что формула, напечатанная в книге, может быть неточной.
(выделено мной)
0
0 / 0 / 0
Регистрация: 27.11.2017
Сообщений: 22
29.07.2018, 14:14
Цитата Сообщение от IGPIGP Посмотреть сообщение
Вы не ответили тогда. Скажите, этот ваш последний пост можно считать ответом? Если да, - можете не отвечать. В знак согласия.
это промежуточные результаты округлять, как в примере, который я привел.
А что касается погрешности, то

function_round (0,12345^2 * 10^5) / 10^5

1) 0,12345*0,12345 = 0,0152399025
2) 0,0152399025*10^5= 1523,99025
потом используем одну из функций которая нам либо округлит в большую, меньшую или вовсе откинет все цифры после зпт. в зависимости от цели автора, получим либо 1523 (в случае отбрасывания или округления до меньшего целого) или 1524 (если округлять к большему или математически правильно)
3) теперь мы обратно делим на 10^5, получаем 0,01523 или 0,01524
4) сравниваем результат пользователя и программный

тут главное нужно знать как и с какой точностью будет считать пользователь (если он в 1 формуле считал до сотых, в другой до миллионных и скачет как горный козел, то тогда остаётся только работать с погрешностями вычислений). Но если он считает с определённой точностью, то я предлагаю дать выбирать пользователю точность расчета. Ибо зачастую в задачах просят до сотых считать, а я люблю делать хорошо и в меру своих знаний и опыта (ну или просто по выпендриваться) и брал всегда тысячные. Возможно, там тоже найдутся выпендрёжники или лентяи считающие до десятых. А чтобы не было крашей от степени (ведь кто-то захочет ввести 12451212512...) задать условие на ввод степени, скажем от 1 до 6.

C++
1
2
3
4
5
6
7
8
9
cout<<"Укажите точность расчёта (1-6) >";
while (cin>>n){
if (n<=0 || n>7)
  cout<< "бла бла";
else
  break;
}
 
function_round (cheslo * 10^n) / 10^n
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,878
29.07.2018, 15:36
SemenTVS, в рассуждениях вроде все правильно
а вот в записи это все таки не Бэйсик
Цитата Сообщение от SemenTVS Посмотреть сообщение
10^n
в Си означает не степень, а операция "исключающее ИЛИ"
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21287 / 8312 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
29.07.2018, 16:59
Цитата Сообщение от nmcf Посмотреть сообщение
Evg, а как правильно-то?
Как правильно что?

Цитата Сообщение от ValeryS Посмотреть сообщение
это не эрзац, сиречь заменитель, а вполне себе прикладные методы,для каждой задачи свой
Я, честно говоря, не совсем понимаю, зачем в процессе вычисления заниматься искусственным "округлением". Если нужно увидеть глазами округлённый результат - пожалуйста, подай в printf соответствующий формат, а в cout - setprecision. В процесс вычислений незачем это втыкать, ибо это просто лишнее действие. А с учётом того, что многим в школе/институте преподают этот метод, как один из методов реального округления (не все преподаватели толком понимают, что они преподают), то в этом смысле он является эрзацем. Ровно как и использование типов double и long double якобы для того, чтобы не было неточностей при вычислениях
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
29.07.2018, 17:38
SemenTVS, если тебе нужны числа строго до сотых, используй long long int, а то, что там запятая находится перед третьим числом, держи в уме (и при задании нового значения)
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21287 / 8312 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
29.07.2018, 18:01
TRam_, а как вычислять, например, квадратный корень?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
29.07.2018, 18:09
Цитата Сообщение от Evg Посмотреть сообщение
а как вычислять, например, квадратный корень?
Ну например тем же методом Герона. Но вот будет ли он расходящимся при таком количестве знаков или всё же сойдётся к корню - вопрос.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21287 / 8312 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
29.07.2018, 18:31
Как-то получается извращения ради извращений. Хотя для простых денежных рассчётов с виду сойдёт, если не уходить в область вычисления банковских процентов или наличия дробного количества актива

Добавлено через 15 минут
Хотя с умножением и делением есть тонкости

0.01 / 0.02 = 0.50

Однако если вещественные числа будем представлять целыми, держа в уме, что два последних разряда на самом деле после запятой, то в реальности получим, 001 / 002 = 0, хотя должны были получить 050. Поэтому перед делением надо делитель на 100 умножить

Умножение косячит аналогично

0.05 * 0.06 = 0.0030

В наших терминах должно получиться 005 * 005 = 000 (поскольку у нас только две цифры после запятой), а потому результат надо ещё на 100 поделить
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.07.2018, 18:31

Каков принцип работы парсера?
Здравствуйте! Можете какой нибудь парсер объяснить? Именно как он работает, можно даже продемонстрировать код с комментариями, буду очень...

Aspnet_regsql: каков принцип работы
Вопрос такого плана - пытаюсь добавить таблички с пользователями с помощью этой утилиты - если добавляю в БД на сервере то добавляется, но...

GZipstream - каков принцип многопоточного сжатия/распаковки?
Добрый день! Интересует тема сходная с https://www.cyberforum.ru/csharp-beginners/thread921121.html. Организовал многопоточное сжатие,...

Каков принцип работы клиент-серверного приложения
Структура прилажения такая: Клиент весит и ждет пока сервер пришлет текст, сервер отсылает клиенту текст, клиент записывает текст в...

Каков принцип работы самого простого web crawler?
Здравствуйте! Каков принцип работы самого простого web crawler? В Интернете нашел несколько вариантов: нужно сохранить все ссылки сайта,...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
Транслитерация текста с кириллицы на латиницу
Maks 11.11.2026
Решил облегчить жизнь себе и коллегам админам при создании электронных почтовых ящиков для пользователей, в результате написал обработку "Транслитерация текста" с кириллицы на латиницу, а в ней. . .
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru