Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.70
ymniktm
3 / 3 / 1
Регистрация: 04.07.2014
Сообщений: 55
#1

В поисках логики - C++

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

Проблема известная но окончательного ответа я так и не нашел...

int a,b;
a=(0.1+0.7)*10;
b=(0.1+0.8)*10;
cout << a << ' ' <<b;
// 7 9
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.10.2014, 14:40     В поисках логики
Посмотрите здесь:

В поисках книги - C++
Брюс Эккель философия с++ 4е издание.

В поисках совершенных абстракций - C++
Для C++ существует огромное множество библиотек выполненных в различных техниках исполнения. Программисты создавшие их следовали разным...

В поисках адреса переменной - Visual C++
Здравствуйте. Вот дали задачки к экзамену, третий день ищу решение никак найти не могу. Подскажите пожалуйста если не сложно. Vusial C++...

В поисках элегантного кода - C++
Всем привет! У меня есть вот такая функция: void Magic2(int condition, int x, int y, int negY, float k, float b, int* pdc, int width) { ...

В поисках хэндла приложения по имени - C++ WinAPI
Привет всем! Помогите разобраться. Почему такой вод код не помогает найти хэндл программы &quot;DoCtrl&quot;? Возвращается NULL. HWND HForm1; ...

Создайте функцию, которая просматривает массив из 10 целых чисел в поисках одинаковых значений. Все найденн - C++
Создайте функцию, которая просматривает массив из 10 целых чисел в поисках одинаковых значений. Все найденные пары программа должна...

Алгебра логики - C++
Друзья можете подсказать какую-нибудь программу на задачу алгебра логики

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
22.10.2014, 17:25     В поисках логики #2
C++
1
a=(float)(0.1+0.7)*10;
Привидение типа. Вы используете внутри вычислений не int переменные, а т.к. int возвращяемое значение - то считаются как int и внутренние (что то типа того).
Nick Alte
Эксперт С++
1608 / 1000 / 118
Регистрация: 27.09.2009
Сообщений: 1,927
Завершенные тесты: 1
22.10.2014, 17:57     В поисках логики #3
Проблема в точности. Идеально точно десятичные дроби в double не помещаются (ну кроме совсем удачных, вроде 0.5), поэтому возникают малюсенькие "подвижки" в числах и в результате вычислений мы получаем чуть-чуть поменьше 0.8 и чуть-чуть побольше 0.9. Для получения предсказуемых результатов нужно выбрать правило округления и пользоваться им. По умолчанию при преобразовании в int попросту отбрасывается дробная часть. Можно пользоваться бухгалтерским округлением, добавляя 0.5 к округляемому значению перед отбрасыванием дробной части.
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
22.10.2014, 18:14     В поисках логики #4
Цитата Сообщение от Nick Alte Посмотреть сообщение
чуть-чуть поменьше 0.8 и чуть-чуть побольше 0.9
Даже при условии что double не точно даёт результат - всё же если делать "0.1+0.7" то будет число приближенное к 0.8, и должно именно оно выйти. Но в данном примере не это суть проблемы, а процесс вычисления, исходя из которого все внутренние переменные примут разрядность того типа, который указан как возвратное значение. Дабы процесс вычисления(чтоб внутренние переменные вычислялись как другой тип) работал при возвратном int и с использованием float(double) нужно приводить тип.
Nick Alte
Эксперт С++
1608 / 1000 / 118
Регистрация: 27.09.2009
Сообщений: 1,927
Завершенные тесты: 1
22.10.2014, 18:59     В поисках логики #5
Цитата Сообщение от Izual Посмотреть сообщение
Но в данном примере не это суть проблемы, а процесс вычисления, исходя из которого все внутренние переменные примут разрядность того типа, который указан как возвратное значение.
Это категорически неверно. Проблема именно в приближённых значениях.
Цитата Сообщение от Izual Посмотреть сообщение
всё же если делать "0.1+0.7" то будет число приближенное к 0.8
Получится. Но будет не ровно 0.8, а чуть меньше. И когда умножим на 10, то получим не ровно 8, а 7.999999.....
После отбрасывания дробной части, которое осуществляется при занесении значения в переменную a, имеющую тип int, остаётся 7.
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
22.10.2014, 19:03     В поисках логики #6
Цитата Сообщение от Nick Alte Посмотреть сообщение
не ровно 8, а 7.999999
Цитата Сообщение от Nick Alte Посмотреть сообщение
тип int, остаётся 7
Почему получится 7, если закон округления должен результировать 8 ?
Nick Alte
Эксперт С++
1608 / 1000 / 118
Регистрация: 27.09.2009
Сообщений: 1,927
Завершенные тесты: 1
22.10.2014, 19:07     В поисках логики #7
Потому что "закон округления" при преобразовании из вещественных чисел в целые выбран однозначно: отбрасывается дробная часть, остаётся целая. Если нужно округление по каким-то другим правилам - извольте считать самостоятельно, к вашим услугам floor, ceil и прочие интересные функции.
ValeryS
Модератор
6537 / 5003 / 460
Регистрация: 14.02.2011
Сообщений: 16,642
22.10.2014, 19:08     В поисках логики #8
Цитата Сообщение от Izual Посмотреть сообщение
"0.1+0.7" то будет число приближенное к 0.8,
0.7999999999999999999999999(9)*10=7,99999999999999999999999(9)
7 и не важно, что 0,99999999999999999999999(9) практически 1 отбросили
у компьютера башка железная, так глубоко мыслить не может
чтобы такого не было
можно сделать так
a=(0.1+0.7+0.05)*10;
b=(0.1+0.8+0.05)*10;
у Evg в блогах хорошо описано это поведение, потеря точности, накопление ошибок
если нужна точность то не надо пользоваться плавающими
например в Бух Учете, там эти округления могут довести до того, что всю бухгалтерию посадят
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
22.10.2014, 19:10     В поисках логики #9
Так, протестировал:
C++
1
a=(0.1+0.71)*10;
даёт результат 8. Исходя из этого получается что округление не работает внутри (0.1+0.7), т.е. оно не работает по математическому закону округления, а иным способом - не учитывается число после запятой. Почему не работает округление - потому что выходной тип int, если был бы float/double, то при вычислении искомого было бы 8 и 9, т.к. "математическое" округление работало бы. О чём я и говорил изначально.
ValeryS
Модератор
6537 / 5003 / 460
Регистрация: 14.02.2011
Сообщений: 16,642
22.10.2014, 19:24     В поисках логики #10
Цитата Сообщение от Izual Посмотреть сообщение
т.е. оно не работает по математическому закону округления,
в математике тоже не один закон округления
есть и отбрасывание дроби

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

"Женщину вынули, автомат вставили"(с) "Кин-дза-дза"
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
22.10.2014, 19:34     В поисках логики #11
Цитата Сообщение от ValeryS Посмотреть сообщение
в математике тоже не один закон округления
Не придирайся к словам, я специально в кавычки взял, чтоб показать общепринятое, а не исключительное.

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

Цитата Сообщение от ValeryS Посмотреть сообщение
кофе, в автомате, стоит 20 рублей, у тебя 19.99
Почему 19.99 получилось... считали сумму 19 целых рулей и 99 копеек, а мы тут по другому считаем, у нас тут разбор корня того как считает система, и в отношении int возвратной, система считает иначе, чтоб она считала по общепринятому мат. закону - надо вставить условие if(drob(num) > 0.5)num=num+1;
По этому прекращяйте следствия показывать, автор ищет причину!
ValeryS
Модератор
6537 / 5003 / 460
Регистрация: 14.02.2011
Сообщений: 16,642
22.10.2014, 19:43     В поисках логики #12
вот и сам блог
http://www.cyberforum.ru/blogs/18334/blog88.html
по моему, очень понятно, почему происходит потеря точности

кстати не компьютерный пример, который может объяснить многое
1/3*3 =1
но стоит только перевести в десятичную дробь
1/3=0.3333333333333333(3)*3=0.999999999999999999999(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??????
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
22.10.2014, 19:57     В поисках логики #13
Цитата Сообщение от Nick Alte Посмотреть сообщение
Если нужно округление по каким-то другим правилам
Достаточно использовать привидение типа.
Цитата Сообщение от ValeryS Посмотреть сообщение
по моему, очень понятно, почему происходит потеря точности
500 строк коментов, 5 ссылок где ещё по 500 строк комментов, а всё свелось к одному слову, которое объясняет причину: "разрядность".
"Краткость - сестра таланта". И не надо тут про движение нейтронов, фатонов и другой чепухи, отводящей от конкретики, в чём я не сомневаюсь вы преуспеете если будете и дальше углубляться в процессы вычислений, зависящих от типа, зависящих от кол-ва чисел, зависящих от разрядности, зависящих от движения электронов, и т.п... кармические реакции..

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

Цитата Сообщение от ValeryS Посмотреть сообщение
а не проще num+0.5??????
Результат будет одинаков, я лишь показал одну из вариаций того как применяется условие того что дробная часть числа > 0.5
Dennis Ritchie
546 / 138 / 29
Регистрация: 27.07.2014
Сообщений: 2,445
22.10.2014, 20:07     В поисках логики #14
Цитата Сообщение от Izual Посмотреть сообщение
И не надо тут про движение нейтронов, фатонов и другой чепухи, отводящей от конкретики...
По-моему, ValeryS как раз и изложил конкретику.
Izual
22.10.2014, 20:22
  #15

Не по теме:

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

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

taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
22.10.2014, 20:32     В поисках логики #16
Цитата Сообщение от 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.1100110011001. Переведём в десятичное. 0.799926758. Тоже меньше. Переведём 0.8 десятичное в двоичный формат. 0.1100110011001. Тоже совпадает. А теперь сложим ещё раз. 0.00011001+0.11001100=0.11100110. В десятичном 0.89453125. Переведём 0.9. 0.11100110. Совпадает. 0.0001100110011+0.1100110011001=0.1110011001100. В десятичном 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. Одна и так же ошибка сработала в две разные стороны.
ymniktm
3 / 3 / 1
Регистрация: 04.07.2014
Сообщений: 55
22.10.2014, 20:33  [ТС]     В поисках логики #17
Всё это писали и на других форумах. Вопрос в другом.
почему (0.1+0.8)*10=9.0000000001,(0.1+0.6)*10=7.00000000001,(0.2+0.7)*10=9,0000000000001 и тп
а (0.1+0.7)*10=7.99999999999 ?
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
22.10.2014, 20:36     В поисках логики #18
Цитата Сообщение от Izual Посмотреть сообщение
Даже при условии что double не точно даёт результат - всё же если делать "0.1+0.7" то будет число приближенное к 0.8, и должно именно оно выйти.
Бред, кобыла нервно травит весь табун. Получается меньше 0.8, а всё, что меньше 0.8, но не меньше 0.7, это 0.7.
ValeryS
Модератор
6537 / 5003 / 460
Регистрация: 14.02.2011
Сообщений: 16,642
22.10.2014, 20:37     В поисках логики #19
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.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.10.2014, 20:41     В поисках логики
Еще ссылки по теме:

Решение задач логики предикатов - C++
Всем привет. Вот уже неделю обдумываю идею написания программы решения задач логики предикатов (конечно самых простых). Знаю, что задача не...

Не понимаю логики освобождения памяти - C++
Не могу понять каким образом освобождается память если ее ячейки всеравно заполнены, и более того в дальнейшем не используются.. ...

Упрощение выражений алгебры логики - C++
Я пытаюсь написать программу для упрощение выражений алгебры логики.Не могу придумать алгоритм для упрощения.Может кто нибудь уже...

Разделение данных и логики и ООП - C++
Тренируюсь в ООП и вообще в C++ и появилась неприятная ошибка. Есть конструктор в классе BaseHouse: BaseHouse(unsigned int height,...

Правильно ли реализованы операторы (в смысле логики)? - C++
mik-a-el, Отписался на форуме-теперь ответь пожалуйста)) bool operator == (complex &amp;c) { if (re==c.re &amp;&amp; im==c.im) ...


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

Или воспользуйтесь поиском по форуму:
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,537
22.10.2014, 20:41     В поисках логики #20
Цитата Сообщение от ymniktm Посмотреть сообщение
Вопрос в другом
Так сразу и надо было задать правильный вопрос. "Половина ответа - в правильно заданном вопросе".

Добавлено через 2 минуты
taras atavin, вася, дочитай до конца пост, корень проблемы в return INT типе.
Ещё бисера метнуть?
Yandex
Объявления
22.10.2014, 20:41     В поисках логики
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru