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

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

22.10.2014, 14:40. Показов 3466. Ответов 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 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru