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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 18, средняя оценка - 4.89
kozlik_kozlik
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99
#1

Засада с машинным эпсилон, или Либо я дурак - C++

07.08.2012, 18:08. Просмотров 2609. Ответов 18
Метки нет (Все метки)

Эту задачку выполняют все начинающие.

Так вот, берём два простеньких кода. Они настолько коротки, тупы и очевидны, что я даже не комментировал их.

Первый, работает нормально.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
 
using std::cout;
using std::endl;
 
#include <iomanip>
 
using std::ios;
using std::setiosflags;
 
int main()
{
    float a, b, e;
    int counter;
 
    e=1.0; b=1.0; a=1.0;
 
    counter=0;
 
    do
    {
        e=e/2;
        a=b+e/2;
 
        counter++;
    }while (a>b);
 
    cout << setiosflags(ios::scientific);
 
    cout << sizeof(e) << endl;
    cout << "eps=" << e << endl;
    cout << "counter=" << counter << endl;
 
    return 0;
}
Второй, тоже вроде с виду пристойный, ещё и короче первого - казалось бы, ляпота!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
 
using std::cout;
using std::endl;
 
#include <iomanip>
 
using std::ios;
using std::setiosflags;
 
int main()
{
    float a, e;
    int counter;
 
    e=1.0; a=1.0;
 
    counter=0;
    while (e/2+a>a)
    {
        e=e/2;
        counter++;
    }
 
    cout << setiosflags(ios::scientific);
 
    cout << sizeof(e) << endl;
    cout << "eps=" << e << endl;
    cout << "counter=" << counter << endl;
 
    return 0;
}
Оба кода написаны с помощью Qt Creator 2.0.1.

Определить машинное эпсилон с помощью первого кода для разных типов можно, меняя одно-единственное слово в тексте, ака тип переменных (ну заломало меня извращаться, пусть будет пока так). Для float код даёт значение эпсилон 1.19e-7, для double 2.22e-16, для long double 1.08e-19. *Голосом Малышевой* Это - нормально.
НО: второй код для ЛЮБОГО типа выдаёт 1.08e-19. То бишь он какого-то хрена полосатого делает преобразование типа. Вопрос: ГДЕ тут это может быть?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.08.2012, 18:08
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Засада с машинным эпсилон, или Либо я дурак (C++):

Или я дурак, или компилятор смеется, вот только чувствую я дурак) - C++
Ввожу 1939 совершенно верно, вожу какое либо число тоже совершенно верно. Не отрабатывает else { } Подскажите чтоль.. ...

Либо я дурак либо.... - C++
Короче задание такое...создать матрицу, определить сумму элементов в тех стлбцах которые не содержат отрицательных элементов...но дело не в...

Кроскомпиляция или в чем засада - C++
Написал не большую программку, которую можно использовать как полосу загрузки в консоли, писал на VS12(Dp) из под win7(32-bit), решил...

Или я дурак или лыжи не едут, склоняюсь к первому. - C++
говорит необъявленный идентификатор относительно всех функций класса notebook. Пробовал все конструкторы методов перекинуть в хедер эффект...

Баг компилятора или я дурак? - C++
До:http://www.cyberforum.ru/attachment.php?attachmentid=840160&amp;stc=1&amp;d=1496427343 ...

Что-то интересное. Или программа, которая принимает либо 1, либо 2 числа - C++
Программа - консольное приложение, в качестве параметров при вызове принимает одно или два целых числа. Как это реализовать на C++? Проще...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
OhMyGodSoLong
~ Эврика! ~
1243 / 992 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
07.08.2012, 20:05 #2
Ну не знаю, вот тут всё работает как надо.
kozlik_kozlik
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99
07.08.2012, 20:31  [ТС] #3
Походу компилятор дурак. Да, Qt подставил подножку, маладец.
Ща пойду обновлюсь. За ссылочку на ресурс, кстати, спасибо, полезная она.

Тока где именно здесь загвоздка - непонятно всё равно. Блин, как только не колдую - не получается.
Avazart
Эксперт С++
7148 / 5325 / 276
Регистрация: 10.12.2010
Сообщений: 23,573
Записей в блоге: 17
07.08.2012, 21:50 #4
Проблема не в IDE ...

Проверил на Builder-е
Код
Текущая кодовая страница: 1251
4
eps=1.084202e-19
counter=63
Для продолжения нажмите любую клавишу . . .
kozlik_kozlik
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99
08.08.2012, 10:09  [ТС] #5
Цитата Сообщение от Avazart Посмотреть сообщение
Проблема не в IDE ...
А в чём же тогда?

Самое странное, что код совершенно законный. Удивительное рядом.
-=ЮрА=-
Заблокирован
Автор FAQ
08.08.2012, 11:49 #6
kozlik_kozlik, никакой компилятор не дурак - у тебя тип счётчика какой?Нука смотрим
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
int counter;
- т.е максимум сможем реализовать около 2.5E6 операций деления, по твоему 1,000006 скажем это число которое отличается от 1-цы в 15-м знаке???
-=ЮрА=-
Заблокирован
Автор FAQ
08.08.2012, 11:54 #7
kozlik_kozlik, вот твой же код только с верными(в плане превышения их макс значений) типами переменных
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iomanip>
#include <iostream>
using namespace std; 
 
int main()
{
    double a = 1;
    double e = 1;
    double counter = 0;
 
    while (a < a + e/2)
    {
        e = e/2;
        counter++;
    }
 
    cout << setiosflags(ios::scientific);
 
    cout << sizeof(e) << endl;
    cout << "eps=" << e << endl;
    cout << "counter=" << counter << endl;
 
    return 0;
}
http://liveworkspace.org/code/5125ab...59ed05f22aaaeb
Миниатюры
Засада с машинным эпсилон, или Либо я дурак  
-=ЮрА=-
Заблокирован
Автор FAQ
08.08.2012, 11:57 #8
PS: этот цикл
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
while (a < a + e/2)
* * {
* * * * e = e/2;
* * * * counter++;
* * }
можно записать вот так, для сокращения записи
C++
1
2
while (a < a + (e /= 2))
        counter++;
ValeryS
Модератор
6556 / 5022 / 464
Регистрация: 14.02.2011
Сообщений: 16,763
08.08.2012, 12:03 #9
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
C++
1
2
3
4
5
6
do
 {
 e=e/2;
 a=b+e/2;
counter++;
 }while (a>b);

Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
C++
1
2
3
4
5
while (e/2+a>a)
 {
 e=e/2;
 counter++;
 }
коды то не равнозначны
в первом идет сравнение с е/4
во втором е/2
первый надо переписать так
C++
1
2
3
4
5
6
do
 {
 e=e/2;
 a=b+e;
counter++;
 }while (a>b);
или так
C++
1
2
3
4
5
6
do
 {
 a=b+e/2;
 e=e/2;
counter++;
 }while (a>b);
Добавлено через 3 минуты
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
что я даже не комментировал их.
а прокомментировал бы нашел бы ошибку
kozlik_kozlik
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99
09.08.2012, 21:46  [ТС] #10
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
kozlik_kozlik, никакой компилятор не дурак - у тебя тип счётчика какой?Нука смотрим
- т.е максимум сможем реализовать около 2.5E6 операций деления, по твоему 1,000006 скажем это число которое отличается от 1-цы в 15-м знаке???
А ты вставь в цикл

cout << counter << endl;

и убедись, что до переполнения тут как до Китая раком. Что такое геометрическая прогрессия, в курсе? Так вот она имеет такое замечательное свойство - очень быстро расти/падать.
ValeryS
Модератор
6556 / 5022 / 464
Регистрация: 14.02.2011
Сообщений: 16,763
09.08.2012, 21:55 #11
kozlik_kozlik,
А ты мое сообщение читал????
у тебя два разных кода
kozlik_kozlik
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99
09.08.2012, 22:20  [ТС] #12
ValeryS, раз коды не равнозначны, то почему дают одинаковый результат (для long double исесьна)? Особенно это хорошо видно, если выводить в процессе номер и эпсилон. Не иначе как б-жье чудо. Равнозначны они. Попробуй просто в голове прокрутить, что там происходит, первые несколько шагов, буквально с калькулятором и текстовым редактором (бумажку не буду рекомендовать, уж так и быть).

Или просто взгляни на консоль, если лень.
Первый код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
 
using std::cout;
using std::endl;
 
#include <iomanip>
 
using std::ios;
using std::setiosflags;
 
int main()
{
    long double a, b, e;
    int counter;
 
    e=1.0; b=1.0; a=1.0;
 
    counter=0;
 
    do
    {
        e=e/2;
        a=b+e/2;
 
        cout << counter << " " << e << endl;
 
        counter++;
    }while (a>b);
 
    cout << endl;
 
    cout << setiosflags(ios::scientific);
 
    cout << sizeof(e) << endl;
    cout << "eps=" << e << endl;
    cout << "counter=" << counter << endl;
 
    return 0;
}
Второй код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
 
using std::cout;
using std::endl;
 
#include <iomanip>
 
using std::ios;
using std::setiosflags;
 
int main()
{
    long double a, e;
    int counter;
 
    e=1.0; a=1.0;
 
    counter=0;
    while (e/2+a>a)
    {
        e=e/2;
 
        cout << counter << " " << e << endl;
 
        counter++;
    }
 
    cout << endl;
 
    cout << setiosflags(ios::scientific);
 
    cout << sizeof(e) << endl;
    cout << "eps=" << e << endl;
    cout << "counter=" << counter << endl;
 
    return 0;
}
Добавлено через 4 минуты
ValeryS, на вот тебе результаты работы первого кода и второго:
http://ideone.com/leMLY
http://ideone.com/3zcTb

Нет тут ошибки.
ValeryS
Модератор
6556 / 5022 / 464
Регистрация: 14.02.2011
Сообщений: 16,763
09.08.2012, 22:52 #13
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
Попробуй просто в голове прокрутить, что там происходит,
кручу
первый код первая проходка(дальше лень)
C++
1
2
3
4
5
6
7
8
  e=1.0; b=1.0; a=1.0;
 do
    {
        e=e/2;// е =0.5
        a=b+e/2;a=1.0+0.25  1.0 +0.5/2
 
        counter++; //1
    }while (a>b);  1.25>1
второй код первая проходка
C++
1
2
3
4
5
6
7
8
 e=1.0; a=1.0;
 
    counter=0;
    while (e/2+a>a)// 0.5+1>1.0 1.5>1.0
    {
        e=e/2; //e= 0.5
        counter++;//1
    }
Если вы считаете что 1.5>1.0 это тоже самое что 1.25>1
тогда извините

Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
то почему дают одинаковый результат (для long double исесьна)?
а для других???
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
Особенно это хорошо видно, если выводить в процессе номер и эпсилон. Не иначе как б-жье чудо.
класная отмазка

Добавлено через 4 минуты
еще раз
Цитата Сообщение от ValeryS Посмотреть сообщение
C++
1
2
3
4
5
6
 do
 {
 e=e/2;
 a=b+e;
counter++;
 }while (a>b)
;
или так
C++
1
2
3
4
5
6
do
 {
 a=b+e/2;
 e=e/2;
counter++;
 }while (a>b)
kozlik_kozlik
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99
09.08.2012, 23:12  [ТС] #14
ValeryS

Если вы считаете что 1.5>1.0 это тоже самое что 1.25>1
тогда извините
А вот я сейчас спрошу, почему должно быть "то же самое", и ты не сможешь ответить.

Давай по порядку. Вот просто по-тупому.

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

Первый код.
Первый оборот цикла: е=0,5, а=1,25, счётчик=1, а отличается от 1, продолжаем.
Второй оборот цикла: е=0,25, а=1,125, счётчик=2, а не отличается от 1, остановились.

Результат: е=0,25, 2 шага.

Второй код.
Первый оборот цикла: сравниваем 1,5 и 1, различается, считаем дальше, е=0,5, счётчик=1.
Второй оборот цикла: сравниваем 1,25 и 1, различаются, считаем дальше, е=0,25, счётчик=2.
Третий оборот цикла: сравниваем 1,125 и 1, не различаются, выходим из цикла.

Результат: е=0,25, 2 шага.

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

класная отмазка
Ага, не верь глазам своим (с) Козьма Прутков.

а для других???
Ты тему-то читал? В Qt Creator и Builder второй код даёт то же самое при любых типах из перечисленных, что и при long double. И именно в этом, если ты не заметил, и состоит проблема. Онлайн-IDE выдаёт абсолютно аналогичные результаты и при float, и при double, и при long double для обоих кодов. Собственно в этом и проблема - в Qt Creator и Builder происходит хреновина. ПРОБЛЕМА НЕ В ЛОГИКЕ ВЫЧИСЛЕНИЯ ЭПСИЛОН. ПРОБЛЕМА В СТРАННОМ ПРЕОБРАЗОВАНИИ ТИПА, КОТОРОГО НЕ ДОЛЖНО БЫТЬ, НО ПРОИСХОДИТ.

Люди, вы чего? Уже второй чудесатый "ответ" в теме. Да с каким гонором-то. Жара что ли так действует?
ValeryS
Модератор
6556 / 5022 / 464
Регистрация: 14.02.2011
Сообщений: 16,763
09.08.2012, 23:34 #15
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
Первый код.
Первый оборот цикла: е=0,5, а=1,25, счётчик=1, а отличается от 1, продолжаем.
Второй оборот цикла: е=0,25, а=1,125, счётчик=2, а не отличается от 1, остановились.
Результат: е=0,25, 2 шага.
Второй код.
Первый оборот цикла: сравниваем 1,5 и 1, различается, считаем дальше, е=0,5, счётчик=1.
Второй оборот цикла: сравниваем 1,25 и 1, различаются, считаем дальше, е=0,25, счётчик=2.
Третий оборот цикла: сравниваем 1,125 и 1, не различаются, выходим из цикла.
Результат: е=0,25, 2 шага.
миль пардон Мин Херц, обосрался
согласен полностью, признаю ошибку

Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
Да с каким гонором-то.
где ты гонор то увидел?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.08.2012, 23:34
Привет! Вот еще темы с ответами:

При изменении каких либо данных программа либо вылетает, либо просто не изменяет данные - C++
Добрый вечер. Только недавно начал заниматься С++. И вот возникли проблемы. При изменении каких либо данных. Программа либо вылетает(Qt),...

две прямые либо паралельны либо совпадают либо не существуют - C++
Д даны числа a1, b1, c1, a2, b2, c2. Напечатать координаты точки пересечения прямых, описываемых уравнениями a1x+b1y=c1 и a2x+b2y=c2, либо...

Программа завершилась машинным кодом (0x0) - C++
#include &quot;stdafx.h&quot; # include &lt;iostream&gt; # include &lt;iomanip&gt; # include &lt;math.h&gt; using namespace std; double xx0, xx1; //...

Выполните арифметические операции сложения, вычитания «машинным» методом - C++
Уважаемый форум! Помогите пожалуйста.Что-то я совсем запуталась. Может кто-то знает, как решить поставленную задачу? Выполните...


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

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

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