Russian Qt Forum

Разное => Говорилка => Тема начата: Igors от Февраль 16, 2017, 15:57



Название: Старая шутка
Отправлено: Igors от Февраль 16, 2017, 15:57
Давеча увидел в разбираемых исходниках
Код
C++ (Qt)
if (!(w >= 0))
 w = 0;
 
И чего он это так написал  ???  :)


Название: Re: Старая шутка
Отправлено: Пантер от Февраль 16, 2017, 16:18
Ох, сколько у меня тут такого говнокода в похапэ. Ну, нравится так человеку писать. Но было еще хуже:

Код
PHP
if (!$w >= 0)
 

Человек был уверен, что он отрицает сравнение.


Название: Re: Старая шутка
Отправлено: gil9red от Февраль 16, 2017, 16:19
Давеча увидел в разбираемых исходниках
Код
C++ (Qt)
if (!(w >= 0))
 w = 0;
 
И чего он это так написал  ???  :)

похоже, при отрицательном значении хотел обнулять :)
но выглядит конструкция пипец как странно, аж мозг выворачивает этой логикой :D


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 16, 2017, 16:40
Возможно тип w определяется в шаблоне или define каким, и может быть как signed так и unsigned. И чтобы компилятор не сыпал предупреждения о сравнении беззнакового типа со знаковым так и написали. Хотя "Никогда не приписывайте злому умыслу то, что вполне можно объяснить глупостью." (https://ru.wikipedia.org/wiki/%D0%91%D1%80%D0%B8%D1%82%D0%B2%D0%B0_%D0%A5%D1%8D%D0%BD%D0%BB%D0%BE%D0%BD%D0%B0)  :D.


Название: Re: Старая шутка
Отправлено: Igors от Февраль 16, 2017, 16:56
Ох, сколько у меня тут такого говнокода в похапэ. Ну, нравится так человеку писать.
Нет, смысл в написанном есть, поэтому и выглядит так странно.

Ну и конечно же, все это "знали", "читали" (так будут уверять когда ответ известен)  :)


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 16, 2017, 17:21
Ну и конечно же, все это "знали", "читали" (так будут уверять когда ответ известен)  :)

Тогда сначала напишите какого типа эта w :).


Название: Re: Старая шутка
Отправлено: kambala от Февраль 16, 2017, 18:30
у этого типа перегружен оператор >=, но не < ?


Название: Re: Старая шутка
Отправлено: Racheengel от Февраль 16, 2017, 18:36
какая разница, какой тип...
говнокод он и есть говнокод)


Название: Re: Старая шутка
Отправлено: Igors от Февраль 17, 2017, 12:02
Тогда сначала напишите какого типа эта w :).
Может еще мамину сисю?  :)
у этого типа перегружен оператор >=, но не < ?
Нет никаких перегрузок
какая разница, какой тип...
говнокод он и есть говнокод)
Ну а почему все что непривычно - так сразу и говнокод? :) Это выражение не тождественно такому
Код
C++ (Qt)
if (w < 0)
w = 0;
 


Название: Re: Старая шутка
Отправлено: Пантер от Февраль 17, 2017, 12:09
Igors, мы тут находимся не твои загадки разгадывать. Если есть что сказать, говори. Если потроллить пришел, то тему я удалю.


Название: Re: Старая шутка
Отправлено: Igors от Февраль 17, 2017, 12:34
Igors, мы тут находимся не твои загадки разгадывать.
Ну если Вы здесь заняты чем-то куда более важным (уж не знаю чем) - то я Вас в тему на аркане не тянул. Как тут один говорил
Цитировать
не нравится - проходи мимо

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


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 17, 2017, 12:36
Ну а почему все что непривычно - так сразу и говнокод? :) Это выражение не тождественно такому
Код
C++ (Qt)
if (w < 0)
w = 0;
 

Даже для типа int не тождественно?


Название: Re: Старая шутка
Отправлено: Igors от Февраль 17, 2017, 13:40
Даже для типа int не тождественно?
В общем случае не тождественно, т.е. существуют типы (в самом языке, не пользовательские) когда де Морган отдыхает  :)
 


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 17, 2017, 13:54
В общем случае не тождественно, т.е. существуют типы (в самом языке, не пользовательские) когда де Морган отдыхает  :)

Я про общий целочисленный тип и не говорил. Для конкретного типа int С++ не тождественно? Или теперь загадку надо переформулировать так: "При каком типе w приведённый фрагмент не является говнокодом?" :).


Название: Re: Старая шутка
Отправлено: sergek от Февраль 17, 2017, 14:27
Или теперь загадку надо переформулировать так: "При каком типе w приведённый фрагмент не является говнокодом?" :).
По-моему, ответ уже был дан:
у этого типа перегружен оператор >=, но не < ?


Название: Re: Старая шутка
Отправлено: Igors от Февраль 17, 2017, 14:27
Или теперь загадку надо переформулировать так: "При каком типе w приведённый фрагмент не является говнокодом?" :).
Почему бы и нет, тоже нормальная формулировка. Для int конечно тождественно

А вообще вещь известнейшая. Но стоит ее чуть-чуть замаскировать... В общем, если уж о говне заговорили, как старый солдатский фокус с лопатой  :)


Название: Re: Старая шутка
Отправлено: Авварон от Февраль 17, 2017, 15:17
Небось опять вещественная арифметика, +/-inf, +/-0, nan. Скука.


Название: Re: Старая шутка
Отправлено: Igors от Февраль 18, 2017, 09:28
Небось - авось, неужели так трудно дать простой грамотный ответ? Напр

Если хотя бы один из аргументов nan, то любое арифметическое сравнение возвращает false, хотя это и противоречит законам логики
Код
C++ (Qt)
float w = sqrt(-1);
if (w >= 0) ..  // false
if (w <= 0) ..  // false
if (w == w) ..  // false, nan не равен самому себе
Возвращаясь к исходному вопросу
Код
C++ (Qt)
if (!(w >= 0)) // если w отрицательно ИЛИ невалидно
Т.е. он застраховался, может раньше где-то насвистел в расчетах. Хотя я не одобряю такой стиль, ни к чему этот вынос мозга, правильно так
Код
C++ (Qt)
if ((w < 0) || IsNan(w)) ..
Но то надо было заводить ф-цию, вероятно хедер. Ну и вообще "короче == круче", не так ли?  :)


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 18, 2017, 13:08
Код:
if (!(w >= 0)) // если w отрицательно ИЛИ невалидно

С "отрицательно" понятно, а "невалидно" - из каких соображений следует? Если установлено, что w типа float.


Название: Re: Старая шутка
Отправлено: Racheengel от Февраль 18, 2017, 15:50
Да нет уж, если логика алгоритма действительно допускает появление и сравнение nan-операндов, то это надо делать до условий, типа:

if (isNaN(w))
// bail out
else
if (w < 0)...

Так и чище, и понятней.


Название: Re: Старая шутка
Отправлено: Old от Февраль 18, 2017, 20:04
Да нет уж, если логика алгоритма действительно допускает появление и сравнение nan-операндов, то это...
... говнокод в квадрате. :)
Если программист ждет в результатах своих вычислений NaN, то сам признается в своей криворукости.


Название: Re: Старая шутка
Отправлено: Igors от Февраль 19, 2017, 11:20
С "отрицательно" понятно, а "невалидно" - из каких соображений следует? Если установлено, что w типа float.
Если w свалилось в nan, то исходный код сработает (сравнение вернет false) и w будет присвоено 0. А в этом случае нет
Код:
if (w < 0)  // false если w = nan

Да нет уж, если логика алгоритма действительно допускает появление и сравнение nan-операндов, то это ..
Я тоже люблю вот так резвенько все решать :) Типа "nan не должен появляться вообще!". Некоторые так и делают
Цитировать
void QVector3D::normalize()

Normalizes the currect vector in place. Nothing happens if this vector is a null vector or the length of the vector is very close to 1.
Так совсем плохо, теперь следов ошибки никаких, и почему не работает - хз. Да и рабочий метод нагрузили парочкой сомнительных fuzzy. А руками тоже неинтересно, напр
Код
C++ (Qt)
float len = vec.length();
if (len > epsilon)
vec /= len;
 
Как, вместо 1 вызова 3 строки ???  :) И чему установить злополучный epsilon? Ах "исходя из требований задачи" (обычное вранье)

if (isNaN(w))
// bail out
else
if (w < 0)...

Так и чище, и понятней.
Ага, ага, а куда рыпнуться если "вскипело" (bail out)? Размазывать мульен exception? В общем, проверка на nan - совершенно легальный и полезный прием. Ну, как и все, хорош в меру


Название: Re: Старая шутка
Отправлено: Old от Февраль 19, 2017, 12:23
Так совсем плохо, теперь следов ошибки никаких, и почему не работает - хз.
Ну конечно, присвоить переменной вместо NaN ноль, это замечательно. И сразу понятно почему не работает. :)

Ага, ага, а куда рыпнуться если "вскипело" (bail out)? Размазывать мульен exception?
Ну как вариант - исключения. В любом случе нужно завершить приложение и отправить его на доработку.

В общем, проверка на nan - совершенно легальный и полезный прием. Ну, как и все, хорош в меру
Конечно, как и деление на 0. :)


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 19, 2017, 14:51
А почему акцент на NAN сделан? Будет w например равно INFINITY: оно для дальнейших вычислений сильно будет отличаться, если бы w было равно NAN? А по условию из первого поста не обнулится.


Название: Re: Старая шутка
Отправлено: Igors от Февраль 20, 2017, 07:03
А почему акцент на NAN сделан? Будет w например равно INFINITY: оно для дальнейших вычислений сильно будет отличаться, если бы w было равно NAN? А по условию из первого поста не обнулится.
Не обнулится (для INF), но знак будет проверен корректно. Отличаться будет: любая арифметика с nan производит nan (размножается очень быстро), а INF легко пресечь обычными средствами, напр
Код
C++ (Qt)
if (!(w >= 0))
w = 0;
else
w = MIN(w, 1.0e+20);  // не nan, можно клампить


Название: Re: Старая шутка
Отправлено: ssoft от Февраль 20, 2017, 08:13
Да нет уж, если логика алгоритма действительно допускает появление и сравнение nan-операндов, то это...
... говнокод в квадрате. :)
Если программист ждет в результатах своих вычислений NaN, то сам признается в своей криворукости.

Абсолютно согласен  ;D.
Правда ошибки такого рода не вполне очевидны, например, математические выражения типа

Код:
acos( cos( a ) * sin( b ) / sin( c ) );

при всех проверках на валидность входящих параметров, вполне может дать NaN, всего лишь из-за того, что cos( a ) * sin( b ) / sin( c ) = 1.0000000000000001.
Но программисты должны помнить и об этом, что вещественные числа в информатике, совсем не то, что в математике.
Приходится писать, что-то типа такого).

Код
C++ (Qt)
d = cos( a ) * sin( b ) / sin( c );
// проверка валидности
assert( ( abs( d ) - 1 ) < eps );
// приближенное вычисление
result = ( abs( d ) <= 1 - eps )
   ? acos( d )
   : ( value > 0 )
       ? 0
       : pi;
 


Название: Re: Старая шутка
Отправлено: Igors от Февраль 20, 2017, 10:16
Приходится писать, что-то типа такого).

Код
C++ (Qt)
d = cos( a ) * sin( b ) / sin( c );
// проверка валидности
assert( ( abs( d ) - 1 ) < eps );
// приближенное вычисление
result = ( abs( d ) <= 1 - eps )
   ? acos( d )
   : ( value > 0 )
       ? 0
       : pi;
 
Если nan уже просочился, то все проверки вернут false. Да и assert и eps здесь ни к чему. Аккуратнее напр так
Код
C++ (Qt)
float d = cos(a) * sin(b) / sin(c);
float d2 = qBound(-1.0f, d, 1.0f);
if (fabs(d - d2) > 0)
d = (value > 0) ? 0 : pi;
else
d = acos(d2);
 
Но можно и так
Код
C++ (Qt)
float d = acos(cos(a) * sin(b) / sin(c));
if (IsNan(d))
d = (value > 0) ? 0 : pi;
 
Хотя эти варианты не тождественны - и не только по скорости


Название: Re: Старая шутка
Отправлено: ssoft от Февраль 20, 2017, 12:00
Здесь eps - очень сильно важна). Значение (для acos) для double с отклонением в 1e-12 можно посчитать несущественным, а вот 1.01 или 2.0 и т.д. означает явную алгоритмическую несогласованность входящих данных.

И важным является написать программу таким образом, чтобы nan не просочился. Последствия могут слишком дорого стоить).


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 20, 2017, 13:18
Не обнулится (для INF), но знак будет проверен корректно. Отличаться будет: любая арифметика с nan производит nan (размножается очень быстро), а INF легко пресечь обычными средствами, напр
Код
C++ (Qt)
if (!(w >= 0))
w = 0;
else
w = MIN(w, 1.0e+20);

Т.е. надо проверять и отсекать не только NAN, но и +-INF, +-0 или ещё что в этом роде. Поэтому я про валидность и спрашивал. Проверка из первого сообщения достаточна для необходимой степени валидности значения float для дальнейших вычислений? Такие корявые проверки каждый раз писать надо? Почему не вынести в функцию с понятным названием и назначением?


Название: Re: Старая шутка
Отправлено: Igors от Февраль 20, 2017, 15:08
И важным является написать программу таким образом, чтобы nan не просочился. Последствия могут слишком дорого стоить).
Такие корявые проверки каждый раз писать надо? Почему не вынести в функцию с понятным названием и назначением?
Ах какими мудрыми (и назидательными) мы становимся когда ответ известен :)  Давайте лучше поумничаем "до того"
Код
C++ (Qt)
float a;
...
float b = sqrt(a);
if (a < 0) b= 0;
Код
C++ (Qt)
float a;
...
float b = (a >= 0) ? sqrt(a)  : 0;
 
Разумеется второй вариант аккуратнее и чуть быстрее. Но есть ли еще какая-то разница?


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 20, 2017, 15:52
При чём тут "до" или "после"? Код надо писать так, чтобы другие его нормально читали, а не шарады разгадывали. Если это единственное место в коде, то можно комментарием сопроводить. Если несколько раз встречается, то в функцию выносить. Есть математические функции (http://en.cppreference.com/w/c/numeric/math) стандартной библиотеки. Одна isnormal (http://en.cppreference.com/w/c/numeric/math/isnormal) чего стоит. Если их недостаточно, то добавлять свои. Например, isNegativeOrNan, для условия из первого сообщения. В ней, в целях оптимизации, можно хоть !(w >= 0) писать, хоть на ассемблере, на читаемость основного кода это уже влиять не будет.


Название: Re: Старая шутка
Отправлено: gil9red от Февраль 20, 2017, 15:58
При чём тут "до" или "после"? Код надо писать так, чтобы другие его нормально читали, а не шарады разгадывали. Если это единственное место в коде, то можно комментарием сопроводить. Если несколько раз встречается, то в функцию выносить. Есть математические функции (http://en.cppreference.com/w/c/numeric/math) стандартной библиотеки. Одна isnormal (http://en.cppreference.com/w/c/numeric/math/isnormal) чего стоит. Если их недостаточно, то добавлять свои. Например, isNegativeOrNan, для условия из первого сообщения. В ней, в целях оптимизации, можно хоть !(w >= 0) писать, хоть на ассемблере, на читаемость основного кода это уже влиять не будет.

Плюсую ;D


Название: Re: Старая шутка
Отправлено: Пантер от Февраль 20, 2017, 15:59
При чём тут "до" или "после"? Код надо писать так, чтобы другие его нормально читали, а не шарады разгадывали. Если это единственное место в коде, то можно комментарием сопроводить. Если несколько раз встречается, то в функцию выносить. Есть математические функции (http://en.cppreference.com/w/c/numeric/math) стандартной библиотеки. Одна isnormal (http://en.cppreference.com/w/c/numeric/math/isnormal) чего стоит. Если их недостаточно, то добавлять свои. Например, isNegativeOrNan, для условия из первого сообщения. В ней, в целях оптимизации, можно хоть !(w >= 0) писать, хоть на ассемблере, на читаемость основного кода это уже влиять не будет.
ППКС


Название: Re: Старая шутка
Отправлено: Igors от Февраль 21, 2017, 10:08
Код надо писать так, чтобы другие его нормально читали, а не шарады разгадывали. Если это единственное место в коде, то можно комментарием сопроводить. Если несколько раз встречается, то в функцию выносить. Есть математические функции (http://en.cppreference.com/w/c/numeric/math) стандартной библиотеки. Одна isnormal (http://en.cppreference.com/w/c/numeric/math/isnormal) чего стоит. Если их недостаточно, то добавлять свои. Например, isNegativeOrNan, для условия из первого сообщения. В ней, в целях оптимизации, можно хоть !(w >= 0) писать, хоть на ассемблере, на читаемость основного кода это уже влиять не будет.
Ну и к чему эта тирада для начинающих? Разве кто-то другого мнения или призывал так писать? Совсем наоборот
Хотя я не одобряю такой стиль, ни к чему этот вынос мозга, правильно так
Однако встретив такую загогулину в чужом коде (см первую фразу первого поста) хорошо бы понять зачем она. А кричать сразу "говнокод" и считать автора глупым - самому можно оказаться в неудобном положении.

Такая же ситуевина и здесь
Код
C++ (Qt)
float a;
...
float b = sqrt(a);
...
if (a < 0) b= 0;
Ну ведь знал же он что sqrt может и не понадобится, но зачем-то поперся его сразу вычислять. Неужели опять лох писал?  :)


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 21, 2017, 11:45
Ну ведь знал же он что sqrt может и не понадобится, но зачем-то поперся его сразу вычислять. Неужели опять лох писал?  :)

Цитировать
- Меня будете называть Евгений... Александр Саныч! Ясно? Я спрашиваю, ясно?
- Ясно.
- Сесть. Как стемнеет, кассу будем брать.
- И он пойдет?
- Все!
- Так он же на этом скачке расколется, редиска, при первом же шухере!

- А ну-ка, поди сюда, Федя, сядь. Возьми бумагу, пиши: редиска - поставь тире - нехороший человек. Раскалываться - это значит предавать, сознаваться. Мягкий знак поставь. Шухер - опасность, скачок - тире - ограбление. Записал?
- Да.
- А теперь, Федя, скажи Васе все, что ты ему сказал раньше, на нормальном, на гражданском языке.
- Этот нехороший человек предаст нас при первой опасности.

У меня такая вот ассоциация возникает :).

Вы лучше опишите контекст, в котором такой код писался. Назначение этой программы. Как давно это было, под какое железо/компилятор. Может условия какие специфичные были. Чтобы можно было понять и посочувствовать этому гражданину :).


Название: Re: Старая шутка
Отправлено: Racheengel от Февраль 21, 2017, 18:17
Цитировать
Неужели опять лох писал?

Ну не знает человек языка толком, почему сразу лох то. Мож студент...

float b = a < 0 ? 0 : sqrt(a);


Название: Re: Старая шутка
Отправлено: Igors от Февраль 22, 2017, 12:37
Вы лучше опишите контекст, в котором такой код писался. Назначение этой программы. Как давно это было, под какое железо/компилятор. Может условия какие специфичные были. Чтобы можно было понять и посочувствовать этому гражданину :).
Компилятор icc.

Ну не знает человек языка толком, почему сразу лох то. Мож студент...
Это для нашего модератора важнейшее "вопросы новичков", а я в ихних исходниках разбираться не собираюсь. Вижу что писал человек очень даже грамотный, похоже в сочувствии совсем не нуждается

Да, собсно я и сам здесь не знаю ответа. Есть кое-какие соображения, но "не факт"



Название: Re: Старая шутка
Отправлено: ViTech от Февраль 22, 2017, 13:41
Вижу что писал человек очень даже грамотный, похоже в сочувствии совсем не нуждается.

Про сочувствие я в том плане, что приходилось писать в каких-нибудь специфичных условиях, под какой-нибудь определённый компилятор с каким-нибудь особенным поведением. Равно как и вам теперь, похоже, можно посочувствовать в том, что приходится разгребать этот код. Хотя даже в этом случае не вижу причин, по которым "человек очень даже грамотный" не мог бы выражаться "на нормальном, на гражданском языке" :).

Конкретно про sqrt: кто его знает, на какую реализацию и поведение он рассчитывал. sqrt может и исключение выкинуть, в коде есть что-нибудь про исключения? Это риторический вопрос :). Да и закладываться на какое-то частное поведение в особом случае - не лучшая идея.


Название: Re: Старая шутка
Отправлено: Igors от Февраль 22, 2017, 14:45
Про сочувствие я в том плане, что приходилось писать в каких-нибудь специфичных условиях, под какой-нибудь определённый компилятор с каким-нибудь особенным поведением. Равно как и вам теперь, похоже, можно посочувствовать в том, что приходится разгребать этот код. Хотя даже в этом случае не вижу причин, по которым "человек очень даже грамотный" не мог бы выражаться "на нормальном, на гражданском языке" :).
Ну зачем такой минор? Почему бы и не посмотреть как другие пишут, это интересно, а при случае и что-то перенять у них? (разумеется не все подряд).

Хотя и не знаю "правельный ответ", но код выше (с немедленным вычислением sqrt) становится совершенно естественным "гражданским языком" если.... сказать или хотите подумать?  :) 


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 22, 2017, 16:30
Хотя и не знаю "правельный ответ", но код выше (с немедленным вычислением sqrt) становится совершенно естественным "гражданским языком" если.... сказать или хотите подумать?  :) 

Давайте уже, срывайте покровы :).


Название: Re: Старая шутка
Отправлено: Racheengel от Февраль 22, 2017, 18:45
Если человек пишет такой код - то у него проблемы с пониманием того, что он делает.
В чем причина, неважно - неопытность, глупость, или наоборот "сильно умный".
Правильный ответ - так делать не надо, неважно, какая за этим стояла идея (хотя скорее всего, никакой).
Хоть малейшее понятие об оптимизации должно присутствовать.


Название: Re: Старая шутка
Отправлено: Old от Февраль 22, 2017, 19:24
Давайте уже, срывайте покровы :).
Очередная попытка выдать говнокод за сакральные знания. :)
Подождем.... :)


Название: Re: Старая шутка
Отправлено: Igors от Февраль 23, 2017, 15:13
Давайте уже, срывайте покровы :).
Он явно рассчитывает на то что sqrt будет вычисляться асинхронно
Код
C++ (Qt)
float b = sqrt(a);  // сразу запускает вычисление
// если тут какой-то код,
// то он будет выполняться параллельно
Тогда все сразу становится очень натуральным. Ну это всего лишь "я так думаю"  :)

неважно, какая за этим стояла идея (хотя скорее всего, никакой).
Ну а вдруг стояла?


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 23, 2017, 15:55
Он явно рассчитывает на то что sqrt будет вычисляться асинхронно

Вот это поворот сюжета :). А куда, и главное когда, возвращается результат вычисления sqrt при таком "асинхронном" вызове? И какие предпосылки в коде говорят о том, что что-то на этом участке может выполняться параллельно?


Название: Re: Старая шутка
Отправлено: Igors от Февраль 23, 2017, 16:35
Вот это поворот сюжета :). А куда, и главное когда, возвращается результат вычисления sqrt при таком "асинхронном" вызове?
Когда вычисленное "а" потребуется. Это небезопасно, напр если sqrt вернет nan, то будет выставлен флаг FPU. И если параллельный код вздумает его читать (ну а вдруг?), то... Упоминание об этом мелькает в доке icc, но ничего о том каким же образом организуется параллельность (может и мифическое :))

И какие предпосылки в коде говорят о том, что что-то на этом участке может выполняться параллельно?
Тогда "все сходится", иначе и не написать


Название: Re: Старая шутка
Отправлено: m_ax от Февраль 23, 2017, 19:17
Цитировать
Тогда все сразу становится очень натуральным. Ну это всего лишь "я так думаю"
Да, да,  с таким подходом можно оправдать любой говнокод)


Название: Re: Старая шутка
Отправлено: Racheengel от Февраль 23, 2017, 19:17
Он явно рассчитывает на то что sqrt будет вычисляться асинхронно
Код
C++ (Qt)
float b = sqrt(a);  // сразу запускает вычисление
// если тут какой-то код,
// то он будет выполняться параллельно

float b = sqrt(a);
float c = b * sin(b);

а так распараллелится? :)


Название: Re: Старая шутка
Отправлено: Old от Февраль 23, 2017, 21:56
а так распараллелится? :)
Конечно. Главное в конце результат проверит на NaN, и если там он, то результат сделать равным 0 (или 100500, кому как нравится). :)


Название: Re: Старая шутка
Отправлено: Igors от Февраль 24, 2017, 12:15
Да, да,  с таким подходом можно оправдать любой говнокод)
Что все в говно ударились? :) Говно- или нет - это уже совершенно др вопрос, это по существу насколько уместен тот или иной прием в конкретном коде. Но сам прием хорошо бы знать (а не глазками лупать :))

Update: ну вот напр не нравится извращенная (с точки зрения обычного восприятия) логика
Код
C++ (Qt)
(!(w >= 0))
И кричим - как будто все дело в этой записи. Но это легко убрать напр
Код
C++ (Qt)
if (!ValidW(w))
...
inline bool ValidW( float w ) { return w >= 0; }
И опять мы достигли того же (проверились на nan) уже без проблем с читабельностью.


Название: Re: Старая шутка
Отправлено: Racheengel от Февраль 24, 2017, 13:25
На nan надо проверять через isNaN(w).
А код (!(w >= 0)) - говно в любом случае, независимо от ожиданий.
Причем что самое страшное здесь - это непортируемая временная бомба.
Возьмет умный компилятор и соптимирует это в if (w < 0) - почему нет? легитимно ведь.
А через время получим крэш и будем думать - WTF?


Название: Re: Старая шутка
Отправлено: Igors от Февраль 25, 2017, 13:09
Возьмет умный компилятор и соптимирует это в if (w < 0) - почему нет? легитимно ведь.
Не легитимно (хотя это не тот вопрос что решается голосованием), и компилятор об этом прекрасно осведомлен  :)

А код (!(w >= 0)) - говно в любом случае, независимо от ожиданий.
Думается такая реакция вызвана просто необычностью этой конструкции (хотя по выносу мозга ой далеко до оператора ()). Меня тоже сходу это смутило, но замешательство длилось неск секунд, потом догадался (сталкивался с подобным раньше). Возможно автор хотел таким образом (лаконично) подчеркнуть что проверяет (напр в читабельном варианте с ValidW это совсем не очевидно).

а так распараллелится? :)
Цитировать
...
..и подошли они к ж/д рельсам. "Звяк" - сказала бензопила, и сломалась.
"Ааа, блин" - сказали суровые сибирские мужики


Название: Re: Старая шутка
Отправлено: Old от Февраль 25, 2017, 16:20
Думается такая реакция вызвана просто необычностью этой конструкции
В конструкции нет ничего не обычного, реакция вызвана исключительно проверкой результата на NaN, вместо контроля входных параметров для тех функций, которые при неверном параметре возвращают тот самый NaN.
Вы же на ноль не делите? Проверяете?


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 25, 2017, 17:59
Кстати, кто сказал, что функции при неверных аргументах бросятся nan возвращать? Та же sqrt например.


Название: Re: Старая шутка
Отправлено: Old от Февраль 25, 2017, 18:44
Кстати, кто сказал, что функции при неверных аргументах бросятся nan возвращать? Та же sqrt например.
http://en.cppreference.com/w/cpp/numeric/math/sqrt


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 26, 2017, 12:35
http://en.cppreference.com/w/cpp/numeric/math/sqrt

Там и не написано, что sqrt обязана NaN возвращать: "If a domain error occurs, an implementation-defined value is returned (NaN where supported)". И для выявления ошибки нужно не возвращаемое значение анализировать, а проверять math_errhandling (http://en.cppreference.com/w/c/numeric/math/math_errhandling).

Не знаю, насколько компилятор в mingw 5.4.0 "supports IEEE floating-point arithmetic (IEC 60559)", но NAN там есть. При этом у меня sqrt от отрицательного числа возвращает это входное число, а не NAN.


Название: Re: Старая шутка
Отправлено: Old от Февраль 26, 2017, 12:38
Чуть ниже раздел Error handling, там есть:
If the implementation supports IEEE floating-point arithmetic (IEC 60559),
    If the argument is less than -0, FE_INVALID is raised and NaN is returned.


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 26, 2017, 12:54
Чуть ниже раздел Error handling, там есть:
If the implementation supports IEEE floating-point arithmetic (IEC 60559),
    If the argument is less than -0, FE_INVALID is raised and NaN is returned.

Тем не менее:
Не знаю, насколько компилятор в mingw 5.4.0 "supports IEEE floating-point arithmetic (IEC 60559)", но NAN там есть. При этом у меня sqrt от отрицательного числа возвращает это входное число, а не NAN.

Это баг или фича? :)

В любом случае это не отменяет факта, что для определения ошибки нужно не возвращаемое значение проверять, а math_errhandling (что в примере к sqrt (http://en.cppreference.com/w/cpp/numeric/math/sqrt) и сделано). Что нудно, не интересно и не так лаконично, как "!(w>=0)" :D. Ну или аргументы проверять и валидные входные данные подавать. Но это совсем не круто и не асинхронно.


Название: Re: Старая шутка
Отправлено: __Heaven__ от Февраль 26, 2017, 13:09
Код
C++ (Qt)
if (w != pow(sqrt(w), 2)){
   ....
}
 
Бам!!!  8) 8) 8)


Название: Re: Старая шутка
Отправлено: Igors от Февраль 26, 2017, 14:43
В любом случае это не отменяет факта, что для определения ошибки нужно не возвращаемое значение проверять, а math_errhandling (что в примере к sqrt (http://en.cppreference.com/w/cpp/numeric/math/sqrt) и сделано). Что нудно, не интересно и не так лаконично, как "!(w>=0)" :D.
Ах как Вы взыскательны :) Однако практически бесконечные проверки Вас быстро вымотают и засорят код. Тогда броситесь в др крайность - ничего не проверять. И.т.д. В общем вариант с проверкой nan отнюдь не плох.
Ну или аргументы проверять и валидные входные данные подавать. Но это совсем не круто и не асинхронно.
Не только. Всегда есть сторонний код. Напр инверсия матриц - Вы можете поручиться что Гаусс не обкакается? Тогда извольте проверить входную матрицу - а как?

Код
C++ (Qt)
if (w != pow(sqrt(w), 2)){
   ....
}
 
Бам!!!  8) 8) 8)
Так оно и будет не равно для некруглых. И от перестановки слагаемых суммв меняется
Код
C++ (Qt)
(a + b) + c != a + (b + c);


Название: Re: Старая шутка
Отправлено: Old от Февраль 26, 2017, 14:52
Не только. Всегда есть сторонний код. Напр инверсия матриц - Вы можете поручиться что Гаусс не обкакается?
А что будете делать, если сторонний код будет делить на ноль? :)

В общем вариант с проверкой nan отнюдь не плох.
Это если бы он работал. А так, как ViTech выше показал, даже корень из отрицательного числа не всегда возвращает NaN. :)


Название: Re: Старая шутка
Отправлено: Racheengel от Февраль 26, 2017, 15:24
Скажу более конкретно:
!(w>=0) - это НЕ проверка на Nan, а лишь желание положиться на определенное поведение компилятора (которому он совершенно не обязан следовать), причем абсолютно не переносимое. Чем это лучше того, что человек вообще не проверит входные данные?
Поэтому говно, однозначно.


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 26, 2017, 16:51
Ах как Вы взыскательны :) Однако практически бесконечные проверки Вас быстро вымотают и засорят код. Тогда броситесь в др крайность - ничего не проверять. И.т.д. В общем вариант с проверкой nan отнюдь не плох.

На мою взыскательность можно забить :), но вычисления прежде всего должны быть корректными, с погрешностью допустимой для поставленной задачи, а не быстрыми и простыми в написании. Полагаясь, что функции в большом выражении могут возвращать NaN, и тогда всё выражение будет равно NaN, можно получить облом. В том же mingw 5.4.0 выражение "sin( sqrt( -3.14 ) )" вполне себе вычисляется и возвращает значение "-0.00159265", которое выглядит вполне нормальным и не NaN.


Название: Re: Старая шутка
Отправлено: Igors от Февраль 27, 2017, 09:02
В том же mingw 5.4.0 выражение "sin( sqrt( -3.14 ) )" вполне себе вычисляется и возвращает значение "-0.00159265", которое выглядит вполне нормальным и не NaN.
Ну что же Вы аргументируете багами конкретного компилятора (http://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg522205.html)? Некорректно

Что касается альтернативы
Код
C++ (Qt)
errno = 0;
float b = sqrt(a);
if (errno == EDOM) ...
Что-то мне совсем не хочется так делать в рабочем коде. Это надо "окружать", разбираться (а вдруг не EDOM а что-то другое?), да и парочка вызовов errno что-то потянет в число-дробилке. В общем, обычная "рекомендация для других", сам рекомендующий вряд ли будет ей следовать :)

Скажу более конкретно:
!(w>=0) - это НЕ проверка на Nan, а лишь желание положиться на определенное поведение компилятора (которому он совершенно не обязан следовать), причем абсолютно не переносимое. Чем это лучше того, что человек вообще не проверит входные данные?
Поэтому говно, однозначно.
"совершенно", "абсолютно" - никогда не верьте таким "превосходным степеням", это банальная попытка "взять на понт" - и ничего более :) Пользуюсь этим приемом со времен CodeWarrior, сколько компиляторов за это время сменил - не считал, ну может десяток. Пока проблем не было. Да и чего это я не должен верить справочнику
Цитировать
If the implementation supports IEEE floating-point arithmetic (IEC 60559),
    If the argument is less than -0, FE_INVALID is raised and NaN is returned.
Ах, возможно я буду работать на платформе где не поддерживается IEC 60559!! Ну если доживу до этого - тогда и буду разбираться  :)


Название: Re: Старая шутка
Отправлено: Old от Февраль 27, 2017, 09:30
Что-то мне совсем не хочется так делать в рабочем коде.
Поэтому и нужно проверять аргументы функции до ее вызова, чтобы не поймать на выходе NaN.


Название: Re: Старая шутка
Отправлено: ViTech от Февраль 27, 2017, 14:46
В том же mingw 5.4.0 выражение "sin( sqrt( -3.14 ) )" вполне себе вычисляется и возвращает значение "-0.00159265", которое выглядит вполне нормальным и не NaN.
Ну что же Вы аргументируете багами конкретного компилятора (http://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg522205.html)? Некорректно

Я поэтому и спрашивал, баг это или фича :). Похоже на баг и дальнейшие расследования привели сюда: sqrt() no longer returns NaN for x less than -0 (https://sourceforge.net/p/mingw-w64/bugs/567/), история изменений sqrt.def.h (https://sourceforge.net/p/mingw-w64/mingw-w64/ci/590ceb54e199239e321c843f060129e5adcccbd3/log/?path=/mingw-w64-crt/math/sqrt.def.h). Больше всего интересен Commit [6617eb] (https://sourceforge.net/p/mingw-w64/mingw-w64/ci/6617ebd5fc6b790c80071d5b1d950e737fc670e1/) и мотивы, по которым поломали поведение по справочнику:
Цитировать
The R language has some hacks specifically for mingw-w64 that were caused by our handling of NaNs in sqrt(x). R uses a special valued NaN to mean 'Not Available' and expects it to be retained through various calculations. Our sqrt(x) doesn't do this, instead it normalises such a NaN (retaining sign).

Т.е. NaN'ы разные бывают :). Кому-то нужен "special valued NaN", но sqrt обрезает до "обычного NaN", и чтобы что-то работало, нужно "some hacks specifically for ..." :D.

Заодно можно посмотреть как проверяют входные данные. Если предположить, что разработчики компилятора лучше знают внутреннюю кухню с float, NaN и прочим, то почему они пишут долго и муторно:
Код
C++ (Qt)
int x_class = fpclassify (x);
if (x_class == FP_NAN || signbit (x))
{ ... }
а не быстро и эффективно:
Код
C++ (Qt)
if (!(x>=0))
{ ... }