Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.53/15: Рейтинг темы: голосов - 15, средняя оценка - 4.53
5 / 5 / 1
Регистрация: 04.07.2014
Сообщений: 73

В поисках логики

22.10.2014, 14:40. Показов 3443. Ответов 41
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Проблема известная но окончательного ответа я так и не нашел...

int a,b;
a=(0.1+0.7)*10;
b=(0.1+0.8)*10;
cout << a << ' ' <<b;
// 7 9
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.10.2014, 14:40
Ответы с готовыми решениями:

Борьба с padding. В поисках логики
Доброго времени суток, господа. Кто мне может объяснить, почему при применении свойства padding к блоку, его размер увеличивается. ...

В поисках AV
Доброго времени суток ув. форумчане. Пожалуй сначала опишу всю структуру ... Гхм. Собственно: Есть две таблицы , одна является...

Проверить истинность формулы логики предикатов. Формулы логики предикатов. Область истинности формулы
Помогите решить задания.Объясните как делать хотя бы первые 2.Или хотя бы укажите источник,благодаря которому получится решить данные...

41
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 17:25
C++
1
a=(float)(0.1+0.7)*10;
Привидение типа. Вы используете внутри вычислений не int переменные, а т.к. int возвращяемое значение - то считаются как int и внутренние (что то типа того).
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
22.10.2014, 17:57
Проблема в точности. Идеально точно десятичные дроби в double не помещаются (ну кроме совсем удачных, вроде 0.5), поэтому возникают малюсенькие "подвижки" в числах и в результате вычислений мы получаем чуть-чуть поменьше 0.8 и чуть-чуть побольше 0.9. Для получения предсказуемых результатов нужно выбрать правило округления и пользоваться им. По умолчанию при преобразовании в int попросту отбрасывается дробная часть. Можно пользоваться бухгалтерским округлением, добавляя 0.5 к округляемому значению перед отбрасыванием дробной части.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 18:14
Цитата Сообщение от Nick Alte Посмотреть сообщение
чуть-чуть поменьше 0.8 и чуть-чуть побольше 0.9
Даже при условии что double не точно даёт результат - всё же если делать "0.1+0.7" то будет число приближенное к 0.8, и должно именно оно выйти. Но в данном примере не это суть проблемы, а процесс вычисления, исходя из которого все внутренние переменные примут разрядность того типа, который указан как возвратное значение. Дабы процесс вычисления(чтоб внутренние переменные вычислялись как другой тип) работал при возвратном int и с использованием float(double) нужно приводить тип.
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
22.10.2014, 18:59
Цитата Сообщение от Izual Посмотреть сообщение
Но в данном примере не это суть проблемы, а процесс вычисления, исходя из которого все внутренние переменные примут разрядность того типа, который указан как возвратное значение.
Это категорически неверно. Проблема именно в приближённых значениях.
Цитата Сообщение от Izual Посмотреть сообщение
всё же если делать "0.1+0.7" то будет число приближенное к 0.8
Получится. Но будет не ровно 0.8, а чуть меньше. И когда умножим на 10, то получим не ровно 8, а 7.999999.....
После отбрасывания дробной части, которое осуществляется при занесении значения в переменную a, имеющую тип int, остаётся 7.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 19:03
Цитата Сообщение от Nick Alte Посмотреть сообщение
не ровно 8, а 7.999999
Цитата Сообщение от Nick Alte Посмотреть сообщение
тип int, остаётся 7
Почему получится 7, если закон округления должен результировать 8 ?
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
22.10.2014, 19:07
Потому что "закон округления" при преобразовании из вещественных чисел в целые выбран однозначно: отбрасывается дробная часть, остаётся целая. Если нужно округление по каким-то другим правилам - извольте считать самостоятельно, к вашим услугам floor, ceil и прочие интересные функции.
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
22.10.2014, 19:08
Цитата Сообщение от Izual Посмотреть сообщение
"0.1+0.7" то будет число приближенное к 0.8,
0.7999999999999999999999999(9)*10=7,9999 9999999999999999999(9)
7 и не важно, что 0,99999999999999999999999(9) практически 1 отбросили
у компьютера башка железная, так глубоко мыслить не может
чтобы такого не было
можно сделать так
a=(0.1+0.7+0.05)*10;
b=(0.1+0.8+0.05)*10;
у Evg в блогах хорошо описано это поведение, потеря точности, накопление ошибок
если нужна точность то не надо пользоваться плавающими
например в Бух Учете, там эти округления могут довести до того, что всю бухгалтерию посадят
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 19:10
Так, протестировал:
C++
1
a=(0.1+0.71)*10;
даёт результат 8. Исходя из этого получается что округление не работает внутри (0.1+0.7), т.е. оно не работает по математическому закону округления, а иным способом - не учитывается число после запятой. Почему не работает округление - потому что выходной тип int, если был бы float/double, то при вычислении искомого было бы 8 и 9, т.к. "математическое" округление работало бы. О чём я и говорил изначально.
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
22.10.2014, 19:24
Цитата Сообщение от Izual Посмотреть сообщение
т.е. оно не работает по математическому закону округления,
в математике тоже не один закон округления
есть и отбрасывание дроби

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

"Женщину вынули, автомат вставили"(с) "Кин-дза-дза"
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 19:34
Цитата Сообщение от ValeryS Посмотреть сообщение
в математике тоже не один закон округления
Не придирайся к словам, я специально в кавычки взял, чтоб показать общепринятое, а не исключительное.

Вы тут разводите демогогию не имеющую отношения к логие задачи, а тема называется "ПОИСК ЛОГИКИ", т.е. автору интересен сам факт того почему его пример не работает так, как мы отталкиваемся от общепринятого. Я показал - логику, а вы показываете брехню, не имеющую отношения к искомой проблеме.

Цитата Сообщение от ValeryS Посмотреть сообщение
кофе, в автомате, стоит 20 рублей, у тебя 19.99
Почему 19.99 получилось... считали сумму 19 целых рулей и 99 копеек, а мы тут по другому считаем, у нас тут разбор корня того как считает система, и в отношении int возвратной, система считает иначе, чтоб она считала по общепринятому мат. закону - надо вставить условие if(drob(num) > 0.5)num=num+1;
По этому прекращяйте следствия показывать, автор ищет причину!
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
22.10.2014, 19:43
вот и сам блог
https://www.cyberforum.ru/blogs/18334/blog88.html
по моему, очень понятно, почему происходит потеря точности

кстати не компьютерный пример, который может объяснить многое
1/3*3 =1
но стоит только перевести в десятичную дробь
1/3=0.3333333333333333(3)*3=0.999999999999 999999999(9)
единицы не получается


компьютер оперирует двоичными числами и многие десятичные конечные дроби для него являются бесконечными
а размер конечен, вот тебе и потеря

хорошо он оперирует с дробями вида1/2n

Добавлено через 6 минут
Цитата Сообщение от Izual Посмотреть сообщение
а вы показываете брехню,
хамить изволите?
Цитата Сообщение от Izual Посмотреть сообщение
не имеющую отношения к искомой проблеме.
а никакой проблемы нет
достаточно литературу почитать, что есть конечная и бесконечная дробь
Цитата Сообщение от Izual Посмотреть сообщение
По этому прекращяйте следствия показывать, автор ищет причину!
а это что
Цитата Сообщение от Nick Alte Посмотреть сообщение
И когда умножим на 10, то получим не ровно 8, а 7.999999.....
После отбрасывания дробной части,
Цитата Сообщение от ValeryS Посмотреть сообщение
7 и не важно, что 0,99999999999999999999999(9) практически 1 отбросили
при приведению к int дробная часть отбрасывается
независимо какая она была
и это не только в Си

Добавлено через 1 минуту
Цитата Сообщение от Izual Посмотреть сообщение
if(drob(num) > 0.5)num=num+1;
а не проще num+0.5??????
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 19:57
Цитата Сообщение от Nick Alte Посмотреть сообщение
Если нужно округление по каким-то другим правилам
Достаточно использовать привидение типа.
Цитата Сообщение от ValeryS Посмотреть сообщение
по моему, очень понятно, почему происходит потеря точности
500 строк коментов, 5 ссылок где ещё по 500 строк комментов, а всё свелось к одному слову, которое объясняет причину: "разрядность".
"Краткость - сестра таланта". И не надо тут про движение нейтронов, фатонов и другой чепухи, отводящей от конкретики, в чём я не сомневаюсь вы преуспеете если будете и дальше углубляться в процессы вычислений, зависящих от типа, зависящих от кол-ва чисел, зависящих от разрядности, зависящих от движения электронов, и т.п... кармические реакции..

Добавлено через 4 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение
хамить изволите?
Если вам истина глаза режет, то это лично ваши проблемы. Слово хоть и вульгарное я использовал, но открывает саму суть того каким путём вы решаете задачу.
Цитата Сообщение от ValeryS Посмотреть сообщение
при приведениИ к int дробная часть отбрасывается
ВОТ это и есть суть, а вы тут начали уже примеры показывать и разглагольствовать как "космические корабли бороздят просторы вселенной"

Цитата Сообщение от ValeryS Посмотреть сообщение
а не проще num+0.5??????
Результат будет одинаков, я лишь показал одну из вариаций того как применяется условие того что дробная часть числа > 0.5
0
 Аватар для Dennis Ritchie
555 / 148 / 58
Регистрация: 27.07.2014
Сообщений: 2,446
22.10.2014, 20:07
Цитата Сообщение от Izual Посмотреть сообщение
И не надо тут про движение нейтронов, фатонов и другой чепухи, отводящей от конкретики...
По-моему, ValeryS как раз и изложил конкретику.
0
22.10.2014, 20:22

Не по теме:

Цитата Сообщение от Dennis Ritchie Посмотреть сообщение
изложил конкретику
Вот вам конкретика:
Цитата Сообщение от ValeryS Посмотреть сообщение
у компьютера башка железная, так глубоко мыслить не может
Глубина мысли зависит от приоритетов и условий..

Тоже чтоль ресетнуть интернет, дабы получить новый ип, зарегиться, зайти и сказать какую нибудь чушь, количество голосов же решает в демократии, да Dennis Ritchie?

0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
22.10.2014, 20:32
Цитата Сообщение от ymniktm Посмотреть сообщение
int a,b;
a=(0.1+0.7)*10;
b=(0.1+0.8)*10;
cout << a << ' ' <<b;
// 7 9
Проблема в ошибке округления. 0.1 десятичное - это сколько двоичное?
0.00011001? Или 0.0001100110011? Или сколько? Где ни остановись, а получается меньше, чем 0.1 десятичное. А 0.7 десятичное - это сколько в двоичном? 0.10110011? Или 0.1011001100110? Это тоже меньше, чем 0.7 десятичное. Сумма тоже получается меньше, чем 0.8 десятичное. 0.00011001+0.10110011=0.11001100. Переведём в десятичное. 0,796875<0.8. А теперь переведём 0.8 десятичное в двоичное. 0.11001100. Совпадает.
0.0001100110011+0.1011001100110=0.110011 0011001. Переведём в десятичное. 0.799926758. Тоже меньше. Переведём 0.8 десятичное в двоичный формат. 0.1100110011001. Тоже совпадает. А теперь сложим ещё раз. 0.00011001+0.11001100=0.11100110. В десятичном 0.89453125. Переведём 0.9. 0.11100110. Совпадает. 0.0001100110011+0.1100110011001=0.111001 1001100. В десятичном 0.899902344. Переведём 0.9. 0.1110011001100. Опять совпадает. Теперь умножим на 1010. 0.11001100*1010=110.11111000. При округлении получается 110, переведём в десятичное и получим 6. 0.11100110*1010=1000.11111100, при округлении получаем 1000, при переводе получаем 8. Но заковыка может крыться в том, как округлены дроби. Округлим 0.00011001, 0.11001100 и 0.11100110 до 5-го разряда после запятой, учитывая два разряда после запятой: 0.00011001= 0.00011, 0.11001100=0.11001, а 0.11100110=0.11101. Первый две дроби уменьшились, а третья увеличилась. Умножим третье значение ещё раз на 1010. Получается 0.11101*1010=1001.00010, при округлении до целых получается 1001, переведём в десятичное и получим 9. Переведём 0.11101 в десятичный формат и получим 0.90625. Одна и так же ошибка сработала в две разные стороны.
0
5 / 5 / 1
Регистрация: 04.07.2014
Сообщений: 73
22.10.2014, 20:33  [ТС]
Всё это писали и на других форумах. Вопрос в другом.
почему (0.1+0.8)*10=9.0000000001,(0.1+0.6)*10=7 .00000000001,(0.2+0.7)*10=9,000000000000 1 и тп
а (0.1+0.7)*10=7.99999999999 ?
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
22.10.2014, 20:36
Цитата Сообщение от Izual Посмотреть сообщение
Даже при условии что double не точно даёт результат - всё же если делать "0.1+0.7" то будет число приближенное к 0.8, и должно именно оно выйти.
Бред, кобыла нервно травит весь табун. Получается меньше 0.8, а всё, что меньше 0.8, но не меньше 0.7, это 0.7.
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
22.10.2014, 20:37
ymniktm, в двоичное дроби переведи
и тогда все будет понятно
Цитата Сообщение от taras atavin Посмотреть сообщение
0.00011001? Или 0.0001100110011? Или сколько? Где ни остановись, а получается меньше, чем 0.1 десятичное. А 0.7 десятичное - это сколько в двоичном? 0.10110011? Или 0.1011001100110? Это тоже меньше, чем 0.7 десятичное. Сумма тоже получается меньше, чем 0.8 десятичное. 0.00011001+0.10110011=0.11001100. Переведём в десятичное. 0,796875<0.8.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 20:41
Цитата Сообщение от ymniktm Посмотреть сообщение
Вопрос в другом
Так сразу и надо было задать правильный вопрос. "Половина ответа - в правильно заданном вопросе".

Добавлено через 2 минуты
taras atavin, вася, дочитай до конца пост, корень проблемы в return INT типе.
Ещё бисера метнуть?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.10.2014, 20:41
Помогаю со студенческими работами здесь

В поисках библиотеки
Я хочу написать игру, которую кратко можно описать как &quot;подрывник&quot; :). Работать я собираюсь следующим образом: есть массив вещественных...

В поисках видеокарты
Всем привет, мне нужно заменить видеокарту, для игрулек, посоветуйте, пожалуйста. =CPU= QuadCore AMD Phenom II X4 B25, 3100 MHz ...

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

в поисках истины.
Добрый день, господа. Короче говоря, меня чуть не выгнали с физфака но помиловали и теперь мне нужно адаптироваться;) - нужно написать 2...

В поисках скрипта
Приветствую всех! Помогите пожалуйста найти Javasciprt который будет осуществлять передвижение содержимого блока вправо или влево по...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru