IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> pow(), C++
сообщение
Сообщение #1


Я.
****

Группа: Пользователи
Сообщений: 809
Пол: Мужской
Реальное имя: Саша

Репутация: -  11  +


pow() некорректно работает если используется инкремент или декремент в его параметрах.
Задание:
Совершая обход так:
1 3 4 10
2 5 9 11
6 8 12 15
7 13 14 16
заполнить матрицу а такими значениями: b11b12...bnn
Kod (Показать/Скрыть)

В таком исполнении pow(b[k++ / N], k % N + 1); работает так как надо (еще недавно и так не работал, но теперь почему-то работает):
результат (Показать/Скрыть)

а в таком pow(b[k / N], ++k % N + 1); - нет:
результат (Показать/Скрыть)


Сообщение отредактировано: sheka -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Главное, ничего не сказал, в чем корявость, что не так, что передаешь в функцию, в конце концов, ОТКУДА эта функция, из <math.h> или из <cmath>, но
Цитата
работает коряво
Интересная постановка вопроса. У меня вот не работает коряво, работает как положено. Если надо - кину код...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Я.
****

Группа: Пользователи
Сообщений: 809
Пол: Мужской
Реальное имя: Саша

Репутация: -  11  +


Исправил.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Ты на самом деле думаешь, что оба эти фрагмента делают одно и то же? Вынужден тебя разочаровать, это не так. Вот тебе простейший тест, доказывающий это:

1) добавляешь небольшую функцию, по имени pow, которая не только вычисляет значение xy, но еще и печатает, для каких аргументов она сработала:
int pow(int x, int y)
{
cout << "pow : x = " << x << " y = " << y << endl;
return std::pow(x, y);
}

, больше в коде ничего менять не надо, тебе и так будет понятно что произойдет дальше.

Итак. Запускаем с pow(b[k++ / N], k % N + 1)
Результат (Показать/Скрыть)

А теперь - запускаем с pow(b[k / N], ++k % N + 1)
Результат (Показать/Скрыть)


И что, ты по-прежнему считаешь, что глючит pow? Может, не надо извращаться при вычислении параметров и добиваться UB (неопределенного поведения), чего ты как раз и добился? Поведение не определено, в зависимости от компилятора, фазы Луны и погоды на Сатурне будут выдаваться разные результаты.

P.S. Кстати, компилятор же предупреждает тебя, что в коде не все в порядке:
In function 'int main()':
main.cpp (24) warning: operation on 'k' may be undefined
main.cpp (27) warning: operation on 'k' may be undefined
=== Build finished: 0 errors, 2 warnings (0 minutes, 1 seconds) ===

Неужели это не наводит на размышления? Или опять не обращаем внимания на предупреждения?


Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Я бы вообще запретил ++ в составе сложных выражений.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Я.
****

Группа: Пользователи
Сообщений: 809
Пол: Мужской
Реальное имя: Саша

Репутация: -  11  +


Хм, я как бы понимаю, что вначале значение пропустило, а поэтому потом что-то дорисовало. Но я думал что в этом виноват pow, и никак не ++.
Компилятор GNU GCC (CodeBlocks 10.05) ничего не выдает.
Объясните, пожалуйста, что делает ++ ужасного.

Сообщение отредактировано: sheka -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
Компилятор GNU GCC (CodeBlocks 10.05) ничего не выдает.
Неправда. Зайди в Project -> Build Options, в Compiler Flags включи "Enable all compiler warnings" (которая -Wall), и пересобери проект. Можешь узнать очень много интересного smile.gif

Теперь по Борщову вопросу, что же такого делает ++. Ответ очень прост: изменяет значение переменной. Вот такой у этого оператора побочный эффект. Как бы, ничего страшного, ведь для этого инкремент и предназначен. Ан нет. Тут есть еще вот какая история: в С/С++ не определен ни порядок вычисления выражений, ни порядок вычисления параметров функции (как следствие - не определен и порядок возникновения побочных эффектов). То есть, сказать по:
while (i < M && 0 <= j) a[i++][j--] = pow(b[k / N], (++k) % N + 1);
, что будет выполнено раньше, вычисление первого параметра со старым значением k, а потом инкремент и вычисление второго параметра с новым значением, или наоборот, сначала значение k инкрементируется, и вычислится второй параметр для pow(), а потом с той, уже увеличенной k, будет вычисляться первый параметр - не может никто. Это компиляторозависимо, и, кроме всего прочего, зависит от оптимизатора, ибо в конечном счете он выбирает, в каком порядке вычислять параметры, чтоб было как можно оптимальней. А это уже неопределенное поведение со всеми вытекающими последствиями: нестабильная работа программы (ты ж сам говорил, что раньше не работало, теперь вдруг заработало, помнишь? Явный признак, что что-то не так), и предупреждение, выдаваемое компилятором. Кстати, с первым вариантом:
while (i < M && 0 <= j) a[i++][j--] = pow(b[k++ / N], k % N + 1);
- абсолютно та же история, побочный эффект присутствует и там, а что если сначала вычислится второй параметр, а только потом - первый? Упс... Опять перестанет работать...

Для гарантированного порядка вычисления - используй временные переменные, тогда UB не будет.

Кстати, разницу между префиксным и постфиксным ++ (да и -- тоже) знаешь?

Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Уникум
*******

Группа: Пользователи
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


Цитата(sheka @ 8.10.2011 23:05) *
Но я думал что в этом виноват pow, и никак не ++.
Я извиняюсь, что встреваю. Просто "понравился" образ мысли, не смог удержаться )).
Шека, тут виноват не ++, и не Pow(), виноват ты сам. Во всех случаях прежде всего надо подозревать себя самого. Всякий раз, когда тебе хочется написать что-то вроде "pow() некорректно работает" - вспомни, что миллионы и миллионы программистов работают и не жалуются.. ))

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

P.S.
Я думал, что на этом форуме, благодаря стараниям volvo/IUnknown (и не только), никто не будет вот так сразу валить на компилятор..


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Цитата(sheka @ 8.10.2011 23:05) *

Объясните, пожалуйста, что делает ++ ужасного.

http://lurkmore.ru/%2B%2Bi_%2B_%2B%2Bi


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Я.
****

Группа: Пользователи
Сообщений: 809
Пол: Мужской
Реальное имя: Саша

Репутация: -  11  +


Volvo,
Цитата
не определен ни порядок вычисления выражений
Вычисление логических выражений по короткой схеме ???

Не думал, что на http://lurkmore.ru есть что-то такое издевательски поучительноеsmile.gif

Сообщение отредактировано: sheka -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Я не про вычисление логических выражений. Я про
int f();
int g();

// ...
test(f(), g());
Какая из функций будет вызвана первой (перефразируем, какой аргумент функции test будет вычисляться сначала), f() или g()? Стандарт на этот вопрос ответа не даёт.

Равно, и на вопрос, как будет вычисляться x+y-z. Сначала x+y, а потом отнимут z, или все-таки сначала y-z, а потом прибавят x (причем тут даже на скобки С++ плевал с высокой колокольни, "приоритеты операций одинаковы - как хочу, так и буду делать, тебя не спросил")... Это тоже называется "порядок не определён"...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 2.12.2021 19:58
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name