Форум программистов, компьютерный форум, киберфорум
Наши страницы

C++

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

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

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

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

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

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

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

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

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

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

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

41
taras atavin
3883 / 1757 / 92
Регистрация: 24.11.2009
Сообщений: 27,566
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. Одна и так же ошибка сработала в две разные стороны.
0
ymniktm
4 / 4 / 1
Регистрация: 04.07.2014
Сообщений: 65
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 ?
0
taras atavin
3883 / 1757 / 92
Регистрация: 24.11.2009
Сообщений: 27,566
22.10.2014, 20:36 #18
Цитата Сообщение от Izual Посмотреть сообщение
Даже при условии что double не точно даёт результат - всё же если делать "0.1+0.7" то будет число приближенное к 0.8, и должно именно оно выйти.
Бред, кобыла нервно травит весь табун. Получается меньше 0.8, а всё, что меньше 0.8, но не меньше 0.7, это 0.7.
0
ValeryS
Модератор
6794 / 5202 / 499
Регистрация: 14.02.2011
Сообщений: 17,459
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.
0
Izual
Нарушитель
14 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 20:41 #20
Цитата Сообщение от ymniktm Посмотреть сообщение
Вопрос в другом
Так сразу и надо было задать правильный вопрос. "Половина ответа - в правильно заданном вопросе".

Добавлено через 2 минуты
taras atavin, вася, дочитай до конца пост, корень проблемы в return INT типе.
Ещё бисера метнуть?
0
taras atavin
3883 / 1757 / 92
Регистрация: 24.11.2009
Сообщений: 27,566
22.10.2014, 20:46 #21
Ты совсем? Если бы приводилось точно представимое, например, (0.5+0)*10, то получилось бы правильно:
0.5 десятичное=0.1 двоичное, 0.1*1010=101.0, округляем и получаем 101 двоичное, переводим в десятичное и получаем 5.
0
Dennis Ritchie
22.10.2014, 20:47
  #22

Не по теме:

Цитата Сообщение от Izual Посмотреть сообщение
количество голосов же решает в демократии, да Dennis Ritchie?
Я предполагал, что вы именно так (подобное) и напишите. Значит, вам нужно лучше познать Бога C++
Если вам интересно, то знайте, что количество голосов не имеет для меня никакого значения. Просто объективное мнение.

0
RefSol
269 / 210 / 52
Регистрация: 31.10.2010
Сообщений: 639
22.10.2014, 20:53 #23
Izual, не совсем так
Цитата Сообщение от Izual Посмотреть сообщение
a=(0.1+0.71)*10;
вот так:

C++
1
2
3
int a,b;
a = (int)(((float)0.1 + (float)0.7) * (float)10.0);
b = (int)(((float)0.1 + (float)0.8) * (float)10.0);
или так

C++
1
2
3
4
5
6
int a,b;
float af, bf;
af = (0.1+0.7)*10.0;
bf = (0.1+0.8)*10.0;
a = (int) af;
b = (int) bf;
а лучше (оптимальнее) так:

C++
1
2
int a = 8;
int b = 9;
Добавлено через 2 минуты
ymniktm, посмотрите стандарт IEEE (ANSI/IEEE Std. 754-1985),
там написано, почему
Цитата Сообщение от ymniktm Посмотреть сообщение
Вопрос в другом.
почему (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 ?
1
Izual
Нарушитель
14 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 21:03 #24

Не по теме:

Цитата Сообщение от Dennis Ritchie Посмотреть сообщение
нужно лучше познать Бога C++
Я бы написал иначе: "бога в С++", и С++ лишь как действие, относительно этого:
Они пребывая в своём заблужденье,
Деянием в йоге(связь) придут к просветленью.
(с БГ)
Цитата Сообщение от Dennis Ritchie Посмотреть сообщение
Я предполагал, что вы именно так (подобное) и напишите.
Значит специально спровоцировали.. ~ ~
Цитата Сообщение от Dennis Ritchie Посмотреть сообщение
Если вам интересно
О вас уже мнение сформированно, уже не интересно.



taras atavin, ох, как с вами сложно, "будете смотреть и не увидите"... Я указал на то что проблема в том, что при использовании INT при вычислении будет результат, отталкивающийся от разрядности, в чём в общем и финал решения проблемы автора. Ещё бисерку? Такое ощущение что троллей кормлю, пора заканчивать этот процесс, а то совсем толстыми станете..

Добавлено через 1 минуту
RefSol, а так?
C++
1
a=(float)(0.1+0.7)*10;
0
ymniktm
4 / 4 / 1
Регистрация: 04.07.2014
Сообщений: 65
22.10.2014, 21:06  [ТС] #25
ValeryS, у всех double чисел есть два варианта представления "чуть больше" и "чуть мненьше".
Если дело в битах то почему нет аналогичной ошибки у (0.1+0.3)*10 ?
Или если следовать рассуждениям taras atavin почему например (int)((0.1+0.1)*10)=2 и (int)((0.7+0.7)*10)=14
0
taras atavin
3883 / 1757 / 92
Регистрация: 24.11.2009
Сообщений: 27,566
22.10.2014, 21:08 #26
Цитата Сообщение от Izual Посмотреть сообщение
taras atavin, ох, как с вами сложно, "будете смотреть и не увидите"... Я указал на то что проблема в том, что при использовании INT при вычислении будет результат, отталкивающийся от разрядности, в чём в общем и финал решения проблемы автора. Ещё бисерку? Такое ощущение что троллей кормлю, пора заканчивать этот процесс, а то совсем толстыми станете..
Не имеет значение, каким образом Вы выведет целую часть, если число получилось меньше 0.8, но не меньше 0.7, то будет выведено 0.7. Проблема в том, что из-за ошибок округления при разборе операндов и вычислении получено меньше 0.8. Когда этих ошибок нет, то результат правильный, хоть к инту приводите, хоть функцию юзайте, лезущую прямо в низкоуровневую дробь, выделяющую целую часть, но возвращающую её в формате плавающей запятой. Это значения не имеет.

Добавлено через 1 минуту
Цитата Сообщение от ymniktm Посмотреть сообщение
Если дело в битах то почему нет аналогичной ошибки у (0.1+0.3)*10 ?
Или если следовать рассуждениям taras atavin почему например (int)((0.1+0.1)*10)=2 и (int)((0.7+0.7)*10)=14
А Вы проанализируйте, какие двоичные числа складываются и умножаются и в какую сторону при этом происходит ошибка округления.
0
ValeryS
Модератор
6794 / 5202 / 499
Регистрация: 14.02.2011
Сообщений: 17,459
22.10.2014, 21:09 #27
Цитата Сообщение от ymniktm Посмотреть сообщение
ValeryS, у всех double чисел есть два варианта представления "чуть больше" и "чуть мненьше".
покажь
лучше на примере из стандарта, ссылку на который дал RefSol,
0
RefSol
269 / 210 / 52
Регистрация: 31.10.2010
Сообщений: 639
22.10.2014, 21:15 #28
Izual,
Цитата Сообщение от Izual Посмотреть сообщение
a=(float)(0.1+0.7)*10;
,
так не верно потому, что тип a (int), т.е. перемененной типа int присваивается float,
в С и С++ преобразование типов должно быть явным.
0
Izual
Нарушитель
14 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,564
22.10.2014, 21:18 #29

Не по теме:

Я уже вошёл во вкус)))

Походу я был прав, и скоро разговор дойдёт до разбора атомов)))



Добавлено через 2 минуты
Цитата Сообщение от RefSol Посмотреть сообщение
так не верно потому, что тип a (int), т.е. перемененной типа int присваивается float
В смысле "присваивается тип"? Он же не может присвоиться(!?), зато использование преобразователя ведёт к вычислению по дробным правилам, включающим правило округления.

Добавлено через 49 секунд
А уже после вычисления результат (float) вида будете округлён в int явный тип... По логике..
0
RefSol
269 / 210 / 52
Регистрация: 31.10.2010
Сообщений: 639
22.10.2014, 21:26 #30
Вот описание стандарта на русском

Добавлено через 1 минуту
Цитата Сообщение от Izual Посмотреть сообщение
В смысле "присваивается тип"? Он же не может присвоиться(!?),
присваивается естественно не тип, а данные, оператор (=) - это оператор присваивания,
а преобразование типов (по стандарту языка) должно быть явным в C и C++

Добавлено через 2 минуты
т.е. например
C++
1
2
3
4
5
float af 5.25;
double ad;
 
ad = (double)af; // правильно
ad = af;            // не правильно (скорее всего компилятор съест но выдаст сообщение)
0
22.10.2014, 21:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.10.2014, 21:26
Привет! Вот еще темы с ответами:

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

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