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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.82
List2006
24 / 16 / 2
Регистрация: 19.12.2009
Сообщений: 366
#1

double и for - C++

28.07.2011, 16:42. Просмотров 1479. Ответов 30
Метки нет (Все метки)

Здравствуйте, объясните пожалуйста почему в операции:
C++
1
for (double y = .1; y != 1.0; y += .1)
получается бесконечный цикл, то есть проскакивает выражение 1.0 == 1.0 - как true

ps я знаю что не корректно использоваться не целочисленный "счетчик", но терзает любопытство почему...
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.07.2011, 16:42
Здравствуйте! Я подобрал для вас темы с ответами на вопрос double и for (C++):

Ошибки error C2296: -: недопустимо, левый операнд имеет тип "double (__cdecl *)(double,double,double - C++
Думаю из-за polp #include<iostream> #include<cmath> #include<cstdlib> using namespace std; double polp(double af,double...

Ошибка: error LNK2001: unresolved external symbol "double __cdecl Akk(double,double,double)" - C++
#include <iostream> #include <cmath> using namespace std; double Akk(double x, double y, double z); int main() { int a, b, c; ...

Почему мы пишем double x (double y)? а не через запятую double x,y - C++
почему мы пишем double x (double y)? а не через запятую double x,y

Исправить ошибки "cannot convert 'double (*)(double)' to 'double'" и "too many arguments to function" - C++
пожалуйста проверьте и помогите исправить ошибки: #include<iostream> #include<stdio.h> #include<math.h> #include<stdlib.h> ...

Почему перестает работать программа при замене double на long double? - C++
Здравствуйте! Прошу помощи чтобы разобраться в следующем вопросе: Нашел программу в интернете, запустил - все работает, но когда решил...

Преобразовать 2 числа int в 1 число float(double) | double int1.int2 - C++
Всем привет. Изучая азы C++, столкнулся с такой проблемой. Есть два значения типа int, их необходимо преобразовать в одно значение типа...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
ForEveR
В астрале
Эксперт С++
7972 / 4734 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
28.07.2011, 16:44 #2
List2006, Архитектура. Где-то на форуме обсуждалось.
0
List2006
24 / 16 / 2
Регистрация: 19.12.2009
Сообщений: 366
28.07.2011, 16:50  [ТС] #3
Цитата Сообщение от ForEveR Посмотреть сообщение
...Где-то...
уж лучше бы ты меня в гугль отправил , а по конкретнее можно где именно это было?
0
diagon
Higher
1929 / 1195 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
28.07.2011, 16:55 #4
Из-за неточности вещественных чисел.
Для примера - посмотрите результат 10./3*3.
0
List2006
24 / 16 / 2
Регистрация: 19.12.2009
Сообщений: 366
28.07.2011, 16:59  [ТС] #5
Цитата Сообщение от diagon Посмотреть сообщение
Из-за неточности вещественных чисел.
Для примера - посмотрите результат 10./3*3.
я это понимаю, но в данном случае же не использовалось деление,
а нули позади числа не имеет значения (как гласит нам математика):
1.0 тоже что и 1.000000000000000000

тут можно сделать вывод что С++ заведома делает число не правильным, дописывая скажем
в 1.0 - 1.00000000000000000001 ?
0
diagon
Higher
1929 / 1195 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
28.07.2011, 17:06 #6
Можно погуглить.
Ну или скомпилить этот код
C++
1
2
3
4
5
6
7
#include <iostream>
#include <iomanip>
int main(){
    double y = 0.1;
    for (; y < 1.0; y += .1);
    std::cout << std::fixed << std::setprecision(16) << y - 1.1;
}
1
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
28.07.2011, 17:09 #7
Потому как 0.1 в двоичной системе счисления - это бесконечная периодическая дробь.
Естественно, при представлении в машине она отсекается-округляется...
Таким образом 10*0.1 != 1.0 для дробных чисел
1
List2006
24 / 16 / 2
Регистрация: 19.12.2009
Сообщений: 366
28.07.2011, 17:47  [ТС] #8
если удлинить выдачу разрядов
std::setprecision(80)

то видно что после 16 добавляются какие то шумы и добавляются они тоже ограниченно (то есть потом идут "нечто" - нули) и для одного и того же значения, скажем "y = .1" - шумы будут постоянны.
Но, если после запятой значение "0", скажем "1.0" то шумы не добавляются.

Отсюда вывод: получается что С++ заведомо добавляет эти шумы чтобы достичь свойств вещественных чисел (то есть это по-моему не прихоть железа, а прихоть потребности сделать не точно).

PS либо шумы это глюк объекта cout.
0
fasked
Эксперт С++
4936 / 2516 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
28.07.2011, 17:50 #9
Цитата Сообщение от List2006 Посмотреть сообщение
если удлинить выдачу разрядов
std::setprecision(80)
Где же Вы столько разрядов в double возьмете? Оо
1
List2006
24 / 16 / 2
Регистрация: 19.12.2009
Сообщений: 366
28.07.2011, 17:55  [ТС] #10
даже при деление "1.0/10.0" - шумы точно такие же как, как если бы была просто константа "0.1".
Напомню что для 1.0 и 10.0 шумов нет.

Добавлено через 1 минуту
Цитата Сообщение от fasked Посмотреть сообщение
Где же Вы столько разрядов в double возьмете? Оо
их нет, но видимо для вычислений они прикручиваются, или опять же говорю глюк cout.
0
ValeryLaptev
Эксперт С++
1041 / 820 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
28.07.2011, 18:05 #11
List2006, какие шумы?!!!!
Фокус в том, что для ВСЕХ дробных чисел, кроме степеней двойки (которые представляются ТОЧНО) при переводе в двоичную систему получите бесконечную дробь. Это математика, а не "шумы"...
2
List2006
24 / 16 / 2
Регистрация: 19.12.2009
Сообщений: 366
28.07.2011, 18:19  [ТС] #12
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
List2006, какие шумы?!!!!
Фокус в том, что для ВСЕХ дробных чисел, кроме степеней двойки (которые представляются ТОЧНО) при переводе в двоичную систему получите бесконечную дробь. Это математика, а не "шумы"...
Какая блин математика, ты код скомпилируй как я тебе говорил с 80 разрядами.
Вот результаты для констант (и где там твоя теория с двойкой??):
0.1 = 0.10000000000000000555111512312578270211815834045410156250000000000000000000000000
0.2 = 0.20000000000000001110223024625156540423631668090820312500000000000000000000000000
0.3 = 0.29999999999999998889776975374843459576368331909179687500000000000000000000000000
0.1 = 0.10000000000000000555111512312578270211815834045410156250000000000000000000000000

0.1 / 2.0 = 0.05000000000000000277555756156289135105907917022705078125000000000000000000000000

сам код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <cstdio>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cmath>
 
using namespace std;
 
int main (int argc, char** argv)
{
        std::cout << std::fixed << std::setprecision(80) 
        << "\n0.1 = " << 0.1
        << "\n0.2 = " << 0.2
        << "\n0.3 = " << 0.3
        << "\n0.1 = " << 0.1
        << "\n0.1 / 2.0 = " << 0.1 / 2.0;
 
    std::cin.get();
    return 0;
}
ps оформление, подключенные библиотеки - это у меня для тестов, я просто скопировал все.
0
fasked
Эксперт С++
4936 / 2516 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
28.07.2011, 18:26 #13
List2006, шумы в голове у Вас, реальных разрядов здесь около 15-16, все остальное мусор, который не относится к числу.

Не по теме:

Надо же так додуматься, и смех и грех

2
List2006
24 / 16 / 2
Регистрация: 19.12.2009
Сообщений: 366
28.07.2011, 18:28  [ТС] #14
это не завесит от памяти, времени, эти шумы постоянны для значений за нулём.
К сожалению не могу попробовать на другом компиляторе (у меня MinGW).

PS какая математика, когда представление в памяти идет не в математических дробях, а банально в битах, где после 16 бит нечего нет. Я не думаю чтобы представить константу компилятор заставляет вычислить её (ему придется каждый раз подбирать для этого значение дроби).

Добавлено через 1 минуту
Цитата Сообщение от fasked Посмотреть сообщение
List2006, шумы в голове у Вас, реальных разрядов здесь около 15-16, все остальное мусор, который не относится к числу.

Не по теме:

Надо же так додуматься, и смех и грех

да я уже и без вас это сказал, факт что числа для константы и для выражении постоянны, не зависят от времени, памяти, и расположение памяти.
0
fasked
Эксперт С++
4936 / 2516 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
28.07.2011, 18:31 #15
Цитата Сообщение от List2006 Посмотреть сообщение
Я не думаю чтобы представить константу компилятор заставляет вычислить её (ему придется каждый раз подбирать для этого значение дроби).
А как еще-то? Просто вычислить придеться всего один раз. А уж при выводе точно каждый раз пересчет идет.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.07.2011, 18:31
Привет! Вот еще темы с ответами:

Какая-нибудь реализация функции void Fun (double in, double *out) - C++
Подскажите, пожалуйста, какую-нибудь любую реализацию прототипа функции: void Fun (double in, double *out)

long double и double в MSVC 12 одно и тоже, нужна информация,желательно быстрей - C++
Здравствуйте все знают что в VC long double и double одно и тоже, да и при простой проверке это легко выясняется, но нужна информация от...

std::copy из vector<double> в *double, непонятный warning - C++
double myD={10,20,30,40,50,60,70}; std::vector&lt;double&gt; myvector (7); std::copy ( myD, myD+7, myvector.begin() ); std::copy (...

invalid operands of types ‘double*’ and ‘double’ to binary ‘operator*’ - C++
#include &quot;mpi.h&quot; #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;math.h&gt; #define count 120 int main(int argc,char *argv) { ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
28.07.2011, 18:31
Ответ Создать тему
Опции темы

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