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

Зачем нужные поразрядные операции. Книга Павловская, Щупак - C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 41, средняя оценка - 4.90
Biblio
2 / 2 / 0
Регистрация: 30.04.2009
Сообщений: 27
19.08.2009, 21:02     Зачем нужные поразрядные операции. Книга Павловская, Щупак #1
Решаю задачу из учебника Павловская, Щупак. С++. Программироание на языке высокого уровня. Структурное программирование. Практикум. Часть 1. Семинар 2. Задача 1. стр. 44. Задачу см. в привязанном файле.

Кажется, я решила задачу, программа работает. Но мне не понятно, зачем авторы пишут про поразрядные операции И и ИЛИ. Мне удалось обойтись без них. Может кто-нибудь объяснить, почему речь идет о поразрядных операциях?
Вот мой код. Вроде, работает.
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
40
41
42
#include <iostream>
using namespace std;
 
int main()
{
    float a = 1, b = 2, c = 3;//действительные числа
    float Xn, Xk, dX, f;//значения функции (начальное, конечное, дельта, результат)
    cout << "Vvedite Xn, Xk, dX: ";
    cin >> Xn >> Xk >> dX;
    cout << "a = " << a << " b = " << b << " c = " << c << endl; 
    cout << "Xn = " << Xn << " Xk = " << Xk << " dX = " << dX << endl; 
    cout << "-----------------" << endl;
    cout << "|   X   |   F   |" << endl;
    cout << "-----------------" << endl;
    for(float x = Xn; x <= Xk; x += dX)
    {
        if(x < 0 && b != 0)
        {   
            f = a*x*x+b;
            cout << "f (x < 0 && b !=0): " << f << endl;
        }
        if(x > 0 && b == 0)
            {
                if(x == c) 
                {
                    cout << "NULL";
                    return 0;
                }
                else 
                {
                    f = (x-a)/(x-c);
                    cout << "f (x > 0 && b == 0): " << f << endl;
                }
            }
        if(x == 0 || (x < 0 && b == 0) || (x > 0 && b != 0))
            {
                f = x/c;
                cout << "f: " << f << endl;
            }
    }
return 0;
}
Заранее спасибо.
Миниатюры
Зачем нужные поразрядные операции. Книга Павловская, Щупак  
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.08.2009, 21:02     Зачем нужные поразрядные операции. Книга Павловская, Щупак
Посмотрите здесь:

Поразрядные операции C++
C++ Поразрядные операции, объясните смысл выражений
Поразрядные операции C++
поразрядные операции C++
поразрядные операции C++
C++ Поразрядные операции
C++ Поразрядные операции
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
M128K145
Эксперт C++
 Аватар для M128K145
8276 / 3495 / 142
Регистрация: 03.07.2009
Сообщений: 10,707
19.08.2009, 21:10     Зачем нужные поразрядные операции. Книга Павловская, Щупак #2
Функция F должна принимать действительное значение, если выражение (А ИЛИ В) И (А ИЛИ С) не равно нулю, и целое в противном случае
в жалком подобии кода это значит грубо говоря это
C++
1
2
3
4
if(((A | B) & (A | C)) != 0)
    return float;
else
    return int;
Если не прав - исправте меня
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
19.08.2009, 21:41     Зачем нужные поразрядные операции. Книга Павловская, Щупак #3
Поразрядные операции могут заменить "обычные логические".
Смысла для вашей задачи нет. Поразрядные операции целесообразны при работе с полями битов (массивы флагов или т.п.) которые представляют сразу несколько значений (сущностей) к которым надо применить единое правило. Классический пример - на адрес "наложить" маску, что бы выделить нужные биты (часть адреса).

В общем, это обычная ерунда препода составлявшего методичку (просто невозможно придумать задачу одновременно достаточно простую и практически релевантную).
Сама задача рассчитана на изучение ветвления - использование оператора if или case/swith. Но, дополнительна "утяжелена" необходимостью выделения целой части, при условии (Ац ИЛИ Вц)И(Ац ИЛИ Сц). Последнюю часть Вы пропустили.

Плюс, сделали ошибку в теле for - у Вас три оператора if идут последовательно, а должны быть вложены.
C++
1
2
3
if ( ) { } // Первое условие и вычисление
else if ( ) { } // Второе условие и вычисление
     else { } // Вычисление по третьему условию без проверки
Biblio
2 / 2 / 0
Регистрация: 30.04.2009
Сообщений: 27
19.08.2009, 21:49  [ТС]     Зачем нужные поразрядные операции. Книга Павловская, Щупак #4
Переделала в соответствии с вашими советами. Подозреваю, что упустила часть задачи. Первоначальный вариант просто считает F исходя из начальных условий, но упускает тот факт, что результаты в таблицу нужно выводить исходя из последнего условия (А ИЛИ В) И (А ИЛИ С).
Посмотрите новый вариант. Сейчас это является решением задачи или нет?
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
using namespace std;
 
int main()
{
    float a = 1.2f, b = 2.3f, c = 3;//действительные числа
    float Xn, Xk, dX, f;//значения функции (начальное, конечное, дельта, результат)
    cout << "Vvedite Xn, Xk, dX: ";
    cin >> Xn >> Xk >> dX;
    cout << "a = " << a << " b = " << b << " c = " << c << endl; 
    cout << "Xn = " << Xn << " Xk = " << Xk << " dX = " << dX << endl; 
    cout << "-----------------" << endl;
    cout << "|   X   |   F   |" << endl;
    cout << "-----------------" << endl;
    if(((int(a) | int(b)) & (int(a) | int(c))) != 0)
    {
        for(float x = Xn; x <= Xk; x += dX)
        {
            if(x < 0 && b != 0)
            {   
                f = a*x*x+b;
                cout << "f (x < 0 && b !=0): " << f << endl;
            }
            else
            {
                if(x > 0 && b == 0)
                {
                    if(x == c) 
                    {
                        cout << "NULL";
                        return 0;
                    }
                    else 
                    {
                        f = (x-a)/(x-c);
                        cout << "f (x > 0 && b == 0): " << f << endl;
                    }
                }
                else            
                {
                    f = x/c;
                    cout << "f: " << f << endl;
                }
            }
        }
    }
    else
    {
        for(float x = Xn; x <= Xk; x += dX)
        {
            if(x < 0 && b != 0)
            {   
                f = int(a)*x*x+int(b);
                cout << "f (x < 0 && b !=0): " << f << endl;
            }
            else
            {
                if(x > 0 && b == 0)
                {
                    if(x == c) 
                    {
                        cout << "NULL";
                        return 0;
                    }
                    else 
                    {
                        f = (x-int(a))/(x-int(c));
                        cout << "f (x > 0 && b == 0): " << f << endl;
                    }
                }
                else            
                {
                    f = x/int(c);
                    cout << "f: " << f << endl;
                }
            }
        }           
    }
return 0;
}
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
19.08.2009, 22:02     Зачем нужные поразрядные операции. Книга Павловская, Щупак #5
Кашмар!
Не знаю, будет работать или нет! Но зачёт за такое поставит только урод.
Само решение должно состоять из двух частей - (1) вычисление функции, (2) - "возможное" отбрасывание дробной части.
А Вы сделали оператор выбора отбрасывания/неотбрасывания дробной части, и в каждую из этих ветвей вставили код, вычисляющий функцию.
Но тело цикла исправили верно. Хотя, сам вывод ёще какой-то корявый и бессмысленный.
Судя по наличию шапки таблицы, операторы типа
cout << "f (x < 0 && b !=0): " << f << endl;
следует заменить на что-то типа
cout << "|" << x << "|"<< f << "|"<<endl; //и добавить выравнивание
novi4ok
549 / 502 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
19.08.2009, 22:09     Зачем нужные поразрядные операции. Книга Павловская, Щупак #6
а зачем так сложно? ведь в условии ясно сказано:

C++
1
2
3
4
5
6
7
if(x < 0 && b != 0){
... делай раз
} else if(x > 0 && b == 0){
... делай два
} else {
... делай три
}
в принципе можно здесь тоже применить поразрядные операции, но глупо и платформозависимо. наверное это ошибка в условии. человек и имел ввиду логические операции сравнения.
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
19.08.2009, 23:15     Зачем нужные поразрядные операции. Книга Павловская, Щупак #7
Цитата Сообщение от novi4ok Посмотреть сообщение
а зачем так сложно?
Задачку до конца дочитайте. Я тоже сперва на выражение посмотрел и долго тупил.
novi4ok
549 / 502 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
20.08.2009, 00:36     Зачем нужные поразрядные операции. Книга Павловская, Щупак #8
Цитата Сообщение от skvor Посмотреть сообщение
Задачку до конца дочитайте. Я тоже сперва на выражение посмотрел и долго тупил.
и действительно... заморочка. но что означает "функция принимает целое значение"? мы сейчас можем долго спорить на эту тему, т.к. существует не один способ как это можно истолковать.
кроме того, нигде не стоит, что начальное, конечное значения и интервал - действительные числа (кстати, в реализации отсутствует проверка на то, что начальное значение меньше конечного, что допускает бесконечный, или по крайней мере очень длинный цикл).
пример толкований:
0. если ля-ля-ля равно нулю, исходные данные преобразуются в целые, дальше - все по целочисленной арифметике.
1. если ля-ля-ля равно нулю, конечный результат преобразуется в целое.
2. если ля-ля-ля равно нулю, конечный результат округляется по правилам округления до ближайшего целого.
3. если ля-ля-ля равно нулю, исходные данные округляется по правилам округления до ближайшего целого, дальше - по целочисленной арифметике.
...
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 00:41     Зачем нужные поразрядные операции. Книга Павловская, Щупак #9
novi4ok, ну, скорее, надо выделять целую часть по "машинным понятиям"
Хотя это не суть, если что - светит замена только одного оператора.
А вот для Aц и других - логичнее именно выделение целой части и работа с ними как с битовыми полями или типа того.
M128K145
Эксперт C++
 Аватар для M128K145
8276 / 3495 / 142
Регистрация: 03.07.2009
Сообщений: 10,707
20.08.2009, 01:01     Зачем нужные поразрядные операции. Книга Павловская, Щупак #10
Цитата Сообщение от skvor Посмотреть сообщение
Плюс, сделали ошибку в теле for - у Вас три оператора if идут последовательно, а должны быть вложены.
Какая разница? Это не ошибка. Ну не выполнилось условие - программа пошла дальше и наткнулась на новое условие, проверила и так далее. Зачем else ставить? Здесь он не нужен.
Цитата Сообщение от skvor Посмотреть сообщение
Кашмар!
Не знаю, будет работать или нет! Но зачёт за такое поставит только урод.
Человек попросил о помощи. Я понимаю, возможно ты знаеш больше чем Biblio, но зто не повод так эмоционально на все ошибки реагировать. Представь, если б на все ошибки которые ты допускаеш так реагировали, тебе бы тоже это не нравилось.
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 01:07     Зачем нужные поразрядные операции. Книга Павловская, Щупак #11
Цитата Сообщение от M128K145 Посмотреть сообщение
Человек попросил о помощи. Я понимаю, возможно ты знаеш больше чем Biblio, но зто не повод так эмоционально на все ошибки реагировать. Представь, если б на все ошибки которые ты допускаеш так реагировали, тебе бы тоже это не нравилось.
Опять по диагонали читаете - то была потенциальная оценка человека, готового поставить зачёт.
Для меня препод-урод - не тот кто студентов пинает, а тот, кто ставит зачёты не за знания по предмету. И эта оценка преподов не зависит от того, является ли его предмет профильным или общеинженерной ("ненужной") дисциплиной.
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
20.08.2009, 05:48     Зачем нужные поразрядные операции. Книга Павловская, Щупак #12
C++
1
cout << "f (x < 0 && b !=0): " << f << endl;
это нужно разделить

C++
1
cout << "f (x < 0 && b !=0): ";
C++
1
cout << f << endl;
потом

C++
1
cout << (IntParts(a, b, c) ? (long) f : f) << endl;
C
1
2
3
4
5
6
int IntParts(int a, int b, int c)
{
    /* (a || b) && (a || c) */
 
    return (a | b) & (a | c) & 1;
}
то есть, вывод f должен быть только один, а случаи просто считают как надо и выводят сообщение; сообщение можно цеплять к указателю - тогда его можно выводить вместе с f

там выше M128K145 уже написал побитовые операции, так что & 1 просто для плавности
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 06:45     Зачем нужные поразрядные операции. Книга Павловская, Щупак #13
Сообщение было отмечено автором темы, экспертом или модератором как ответ
accept, попробуйте скомпилировать
cout << (IntParts(a, b, c) ? (long) f : f) << endl;
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
20.08.2009, 08:18     Зачем нужные поразрядные операции. Книга Павловская, Щупак #14
C++
1
cout << (IntParts((int) a, (int) b, (int) c) ? (long) f : f) << endl;
явное приведение, вообще оно приводит к типам в прототипе
поэтому можно делать free(p); без приведения

Добавлено через 1 час 5 минут 15 секунд
для C++ всё таки обязательно приводить, потому что там бывают перегруженные функции и от типов аргументов зависит какой из вариантов одной функции должен сработать
Biblio
2 / 2 / 0
Регистрация: 30.04.2009
Сообщений: 27
20.08.2009, 12:21  [ТС]     Зачем нужные поразрядные операции. Книга Павловская, Щупак #15
Спасибо всем огромное за комментарии. Если я правильно понимаю, вся загвоздка задачи в этой фразе: "Функция F должна принимать действительное значение, если выражение (Ац ИЛИ Вц) И (Ац ИЛИ Сц) не равно нулю, и целое в противном случае".
Я ее понимаю так:
Функция F должна быть равна действительному (вещественному, т.е. в нашем случае float числу), если выражение (Ац ИЛИ Вц) И (Ац ИЛИ Сц) НЕ РАВНО нулю, и F должна быть равна целому числу (в нашем случае int), если выражение (Ац ИЛИ Вц) И (Ац ИЛИ Сц) РАВНО нулю. При этом выражение (Ац ИЛИ Вц) И (Ац ИЛИ Сц), содержит поразрядные операции, т.е. фактически в нем вычисляется булево выражение (A&B)|(A&C) которое проверяется на равенство нулю.
Я переделала код, только теперь не знаю, как проверить, правильно ли он работает. Если выражение (Ац ИЛИ Вц) И (Ац ИЛИ Сц) считает нолики и единицы, то как мне проверить правильность работы программы? У меня это выражение всегда не равно нулю.
Плюс, у программы странное поведение при переходе через ноль. При значениях дельты 0.1, 0.2, 0.4 при переходе через ноль в значение функции попадает какой-то мусор. При других значениях дельты выражение f=x/c считается нормально, т.е. f= 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
using namespace std;
 
int main()
{
    float a = 1.2f, b = 2.3f, c = 3;//действительные числа
    float Xn, Xk, dX, f;//значения функции (начальное, конечное, дельта, результат)
    cout << "Vvedite Xn, Xk, dX: ";
    cin >> Xn >> Xk >> dX;
    if(Xk<=Xn)
    {
        cout << "Ntpravilno vvedeni dannie. Xk ne m/b < Xn\n";
        cout << "Vvedite Xn, Xk, dX: ";
        cin >> Xn >> Xk >> dX;
    }
    cout << "a = " << a << " b = " << b << " c = " << c << endl; 
    cout << "Xn = " << Xn << " Xk = " << Xk << " dX = " << dX << endl; 
    cout << "-----------------" << endl;
    for(float x = Xn; x <= Xk; x += dX)
    {
        //Вычисление функции
        if(x < 0 && b != 0)
        {   
            f = a*x*x+b;
            cout << "При х = " << x << "; f (x < 0 && b !=0) = " << f << endl;
        }
        else
        {
            if(x > 0 && b == 0)
            {
                if(x == c) 
                {
                    cout << "На ноль делить нельзя";
                    return 0;
                }
                else 
                {
                    f = (x-a)/(x-c);
                    cout << "При х = " << x << "; f (x > 0 && b == 0) = " << f << endl;
                }
            }
            else            
            {
                f = x/c;
                cout << "При х = " << x << "; f = " << f << endl;
            }
        }
        //Приведение ее к нужному значению в связи с условием.
        if(((int(a) | int(b)) & (int(a) | int(c))) != 0)
        {
            cout << "Неприведенное значение F = " << f << "   |\n";
            cout << "-----------------" << endl;
        }
        else
        {
            cout << "При х = " << x << " Приведенное значение F = " << int(f) << "   |\n";
            cout << "-----------------" << endl;
        }
 
    }
return 0;
}
Простите за дотошность. Просто хочется понять задачу.
Для
Цитата Сообщение от skvor Посмотреть сообщение
Кашмар!
В августе зачеты никто не ставит. Есть еще просто интерес
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 20:12     Зачем нужные поразрядные операции. Книга Павловская, Щупак #16
Цитата Сообщение от Biblio Посмотреть сообщение
В августе зачеты никто не ставит. Есть еще просто интерес
Да-а, а я думал на осень хвост оставили

Относительно мусора - непонятно, где, через какой ноль, кто переходит?
М.б. проблема в том, что прибавляя к целому отрицательному дельту 0.1 не возникает условия равенства нулю. Например если к -1 десять раз прибавить 0.1, то нуля не будет - получится что-то очень близкое к нулю, но не ноль. Это особенность процессорного представления десятичных дробей, которые невозможно точно представить двоичными числами. В результате, при значении аргумента близкого к нулю вы проходите ветвь с делением, а деление на "очень" малое, приводит к переполнению. Но это только предположение.
Biblio
2 / 2 / 0
Регистрация: 30.04.2009
Сообщений: 27
20.08.2009, 20:15  [ТС]     Зачем нужные поразрядные операции. Книга Павловская, Щупак #17

Спасибо. Проверю ваше предположение. А про общее решение задачи что скажете? Правильно я ее понимаю или нет?
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 20:55     Зачем нужные поразрядные операции. Книга Павловская, Щупак #18
1) Не стоит в if(...) сравнивать с нулём - любое выражение/значение при равенстве нулю - соответствует false, при неравенстве - true
Т.е. if(x > 0 && b == 0) можно заменить на if(x > 0 && b) и переставить ветви then-else
Аналогично (x < 0 && b != 0) тождественно (x < 0 && b)

2) Нелогично для табуляции задавать интервал и приращение.
Нужно либо
- Интервал табуляции (начало и конец) и число шагов
- Начальная точка, шаг (приращение) и число шагов
Alexandoros
226 / 64 / 4
Регистрация: 02.06.2009
Сообщений: 280
20.08.2009, 21:06     Зачем нужные поразрядные операции. Книга Павловская, Щупак #19
Кажется, я решила задачу, программа работает. Но мне не понятно, зачем авторы пишут про поразрядные операции И и ИЛИ. Мне удалось обойтись без них. Может кто-нибудь объяснить, почему речь идет о поразрядных операциях?
Странно что никто не ответил.

Потому что логические и порязрядные операции дают разные результаты.
0xF0 && 0x0F -> true
0xF0 & 0x0F -> false
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.08.2009, 21:25     Зачем нужные поразрядные операции. Книга Павловская, Щупак
Еще ссылки по теме:

C++ Правильно ли я написал программу? Из книжки Павловская Щупак
C++ Поразрядные операции (&,|,^)
C++ Поразрядные операции
Поразрядные операции C++
Поразрядные операции C++

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

Или воспользуйтесь поиском по форуму:
skvor
640KB мне хватило на всё.
118 / 49 / 2
Регистрация: 07.06.2009
Сообщений: 442
20.08.2009, 21:25     Зачем нужные поразрядные операции. Книга Павловская, Щупак #20
Цитата Сообщение от Alexandoros Посмотреть сообщение
Потому что логические и порязрядные операции дают разные результаты.
Оператор разыменовывания указателя и вычисление квадратного корня, тоже дают разные результаты.
Мотивы автора уже не определить. Но мысль правильная.
Yandex
Объявления
20.08.2009, 21:25     Зачем нужные поразрядные операции. Книга Павловская, Щупак
Ответ Создать тему
Опции темы

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