Russian Qt Forum
Ноябрь 25, 2024, 17:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 5   Вниз
  Печать  
Автор Тема: Старая шутка  (Прочитано 40243 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #15 : Февраль 17, 2017, 14:27 »

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

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

Сообщений: 3260


Просмотр профиля
« Ответ #16 : Февраль 17, 2017, 15:17 »

Небось опять вещественная арифметика, +/-inf, +/-0, nan. Скука.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #17 : Февраль 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)) ..
Но то надо было заводить ф-цию, вероятно хедер. Ну и вообще "короче == круче", не так ли?  Улыбающийся
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #18 : Февраль 18, 2017, 13:08 »

Код:
if (!(w >= 0)) // если w отрицательно ИЛИ невалидно

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

Пока сам не сделаешь...
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #19 : Февраль 18, 2017, 15:50 »

Да нет уж, если логика алгоритма действительно допускает появление и сравнение nan-операндов, то это надо делать до условий, типа:

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

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

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #20 : Февраль 18, 2017, 20:04 »

Да нет уж, если логика алгоритма действительно допускает появление и сравнение nan-операндов, то это...
... говнокод в квадрате. Улыбающийся
Если программист ждет в результатах своих вычислений NaN, то сам признается в своей криворукости.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #21 : Февраль 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 - совершенно легальный и полезный прием. Ну, как и все, хорош в меру
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #22 : Февраль 19, 2017, 12:23 »

Так совсем плохо, теперь следов ошибки никаких, и почему не работает - хз.
Ну конечно, присвоить переменной вместо NaN ноль, это замечательно. И сразу понятно почему не работает. Улыбающийся

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

В общем, проверка на nan - совершенно легальный и полезный прием. Ну, как и все, хорош в меру
Конечно, как и деление на 0. Улыбающийся
« Последнее редактирование: Февраль 19, 2017, 12:26 от Old » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #23 : Февраль 19, 2017, 14:51 »

А почему акцент на NAN сделан? Будет w например равно INFINITY: оно для дальнейших вычислений сильно будет отличаться, если бы w было равно NAN? А по условию из первого поста не обнулится.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Февраль 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, можно клампить
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #25 : Февраль 20, 2017, 08:13 »

Да нет уж, если логика алгоритма действительно допускает появление и сравнение nan-операндов, то это...
... говнокод в квадрате. Улыбающийся
Если программист ждет в результатах своих вычислений NaN, то сам признается в своей криворукости.

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

Код:
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;
 
« Последнее редактирование: Февраль 20, 2017, 08:20 от ssoft » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Февраль 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;
 
Хотя эти варианты не тождественны - и не только по скорости
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #27 : Февраль 20, 2017, 12:00 »

Здесь eps - очень сильно важна). Значение (для acos) для double с отклонением в 1e-12 можно посчитать несущественным, а вот 1.01 или 2.0 и т.д. означает явную алгоритмическую несогласованность входящих данных.

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

Сообщений: 858



Просмотр профиля
« Ответ #28 : Февраль 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 для дальнейших вычислений? Такие корявые проверки каждый раз писать надо? Почему не вынести в функцию с понятным названием и назначением?
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #29 : Февраль 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;
 
Разумеется второй вариант аккуратнее и чуть быстрее. Но есть ли еще какая-то разница?
Записан
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.478 секунд. Запросов: 23.