Б)
Как тогда в битах состояние для плюс бесконечности хранится? А для минус (видимо старший бит)?
В)
nan Как хранится по битам?
Г)
Удобно ли что (nan == nan) == false ? Ведь партиал ордеринг звучит как излишнее усложнение...
Я бы сделал что nan < -inf И что nan == nan
Ох, есть же quiet/signaling ...
зы)
Интересуют и мобайл фоны в том числе, не только пека.
Д)
Какие бы в идеале вы хотели методы сравнения для дробных? Помимо > <
Всё верно выдаёт. Учесть однако, что:
1) Есть к нему single precision (32 бита), есть float16 и bfloat16, есть четверной точности (128 бит), есть в стандарте правила неограниченного расширения, у всех метод одинаков, меняется только ширина полей порядка (exponent) и мантиссы (точнее, significand — искусственное слово со смыслом "мантисса или другое что лежит на том же месте").
2) Есть ещё десятичные форматы (вживую встретишь только на технике IBM), у них другие правила.
Здравствуйте, Sm0ke, Вы писали:
S>Удобно ли что (nan == nan) == false ? Ведь партиал ордеринг звучит как излишнее усложнение...
Есть numbers и not-a-numbers. Для первых порядок определён полность, а вторым зачем порядок?
S>Я бы сделал что nan < -inf И что nan == nan
nan это такой способ всё сломать в вычислениях и fail fast. Если обрабатывать nan как число, то ошибка может раствориться.
Это пост из серии, где чел пилит свой язык/компилятор/ОС, критикует все фундаментальные основы и потом пол жизни пишет hello-world в стиле, как ему кажется, идеальней, чем сама природа?
Здравствуйте, cppguard, Вы писали:
S>>Удобно ли что (nan == nan) == false ? Ведь партиал ордеринг звучит как излишнее усложнение... C>Есть numbers и not-a-numbers. Для первых порядок определён полность, а вторым зачем порядок?
Например, чтобы не мучаться с тем, что нельзя даже формально сравнить два float где это надо, или отсортировать массив floatʼов.
Попробуй это сделать в Rust.
error[E0277]: the trait bound `{float}: Ord` is not satisfied
--> src/main.rs:3:5
|
3 | floats.sort();
| ^^^^^^ ---- required by a bound introduced by this call
| |
| the trait `Ord` is not implemented for `{float}`
А сделать ordered map по ним? То же самое.
Формально он прав, конечно.
Но после C/C++, которые плевали на то, что для float/double не определён полный порядок, и сортируют такое как хотят — выглядит дико и непривычно, приходится подставлять подпорки такие или такие.
Кстати, можешь сравнить сортировку двух массивов floatʼов с NaN внутри через std::sort и через qsort. В некоторых рантаймах они будут различны
S>>Я бы сделал что nan < -inf И что nan == nan C>nan это такой способ всё сломать в вычислениях и fail fast. Если обрабатывать nan как число, то ошибка может раствориться.
А какое отношение это имеет к сравнению, когда одновременно оказываются ложными a<b,
a==b и a>b, если одно из них NaN? Тут ошибка не растворится, результат всё равно будет какой-то, и, вероятно, неправильный, если на это не заточились. Может пойти по некорректной ветке алгоритма и самим этим переходом замаскировать ошибку. Например, если условие D>=0 означает наличие корней уравнения, то написать алгоритм в виде
if (d >= 0) { записать корни; }
else { записать признак отсутствия корней; }
без проверки на NaN значит, что будет утвердительно выдан признак отсутствия, а что вычисления пошли неправильно, замаскируется...
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, cppguard, Вы писали:
На все вопросы ответ один: NaN в райнтайме это очень-очень плохо, и если он появился, то в коде кто-то навалил кучу, и нужно разбираться. Решение ничего не делать с NaN и возвращать false на любые проверки я считаю верным, потому что что ни придумывай, всё равно найдётся условие, при котором всё сломается. NaN невозможно обработать каким-либо способом, кроме как сказать "мы где-то обосрались в вычислениях", но это хорошая заглушка для возвращения результата математическими функциями для значений вне области определения. Математический null. Для null же нет логики кроме успешного срабатывания free()? Поэтому не вижу смысла вводить какую-то логику для NaN.
P.S. В С++ вон уже 20 лет пытаются предусмотреть "все случаи", а с каждым разом "случаев" появляется всё больше. Каждый раз как открываю cppreference и читаю "появилось в 2011, deprecated в 2017" начинет закрадываться сомнение по поводу адекватности авторов стандарта.
Здравствуйте, cppguard, Вы писали:
C>На все вопросы ответ один: NaN в райнтайме это очень-очень плохо, и если он появился, то в коде кто-то навалил кучу, и нужно разбираться.
Тут пока верно, только надо понимать, что отладка математики это процесс в разы кошмарнейший за дискретные данные, типа "тут пришёл не тот объект". Съедет где-то посредине точность на 1e-6 — поползли кривые данные — и ещё хорошо, если Inf и NaN, а если формально валидные числа?
C> Решение ничего не делать с NaN и возвращать false на любые проверки я считаю верным, потому что что ни придумывай, всё равно найдётся условие, при котором всё сломается. NaN невозможно обработать каким-либо способом, кроме как сказать "мы где-то обосрались в вычислениях", но это хорошая заглушка для возвращения результата математическими функциями для значений вне области определения. Математический null. C> Для null же нет логики кроме успешного срабатывания free()? Поэтому не вижу смысла вводить какую-то логику для NaN.
Вот и ты стал путать null как "точно нет значения" и null как "хрен его знает", успешно повторив ошибку 99% тех, кто использует SQL.
(Да, тут сами авторы SQL... мнэээ... ошиблись. Но это не полный повод повторять за ними.)
C>P.S. В С++ вон уже 20 лет пытаются предусмотреть "все случаи", а с каждым разом "случаев" появляется всё больше. Каждый раз как открываю cppreference и читаю "появилось в 2011, deprecated в 2017" начинет закрадываться сомнение по поводу адекватности авторов стандарта.
Здравствуйте, netch80, Вы писали:
N>Тут пока верно, только надо понимать, что отладка математики это процесс в разы кошмарнейший за дискретные данные, типа "тут пришёл не тот объект". Съедет где-то посредине точность на 1e-6 — поползли кривые данные — и ещё
хорошо, если Inf и NaN, а если формально валидные числа?
Мне не доводилось работать с подобными проблемами. Я либо использовал алгоритм, который математически устойчив (что доказано формально, а реализация проверена тестами), либо алгоритмы обработки потоков, где единственное, за чем нужно следить — погрешность округления арифметических операций, которая на больших объёмах данных может себя проявить. В этом случае используется FMA, её рукописный аналог или вообще обёртка типа DoubleSummaryStatistics из Java. В такой ситуации NaN-ы избегаются легко — стопицот раз проверяешь выкладки на предмет неопределённости: деление на ноль, тригонометрия, квадратные корни и т.д.
N>Вот и ты стал путать null как "точно нет значения" и null как "хрен его знает", успешно повторив ошибку 99% тех, кто использует SQL. N>(Да, тут сами авторы SQL... мнэээ... ошиблись. Но это не полный повод повторять за ними.)
Так... а как нужно трактовать null, nil и иже с ними? Я говорил не про SQL, а про null-значение в целом.
Здравствуйте, cppguard, Вы писали:
N>>Тут пока верно, только надо понимать, что отладка математики это процесс в разы кошмарнейший за дискретные данные, типа "тут пришёл не тот объект". Съедет где-то посредине точность на 1e-6 — поползли кривые данные — и ещё C>хорошо, если Inf и NaN, а если формально валидные числа?
C>Мне не доводилось работать с подобными проблемами. Я либо использовал алгоритм, который математически устойчив (что доказано формально, а реализация проверена тестами),
Ну значит повезло. А то в общем случае решение типовой СЛАУ уже имеет проблемы с устойчивостью в некоторых случаях.
N>>Вот и ты стал путать null как "точно нет значения" и null как "хрен его знает", успешно повторив ошибку 99% тех, кто использует SQL. N>>(Да, тут сами авторы SQL... мнэээ... ошиблись. Но это не полный повод повторять за ними.)
C>Так... а как нужно трактовать null, nil и иже с ними? Я говорил не про SQL, а про null-значение в целом.
Нужно трактовать так, какова их семантика.
И тут общего рецепта не будет. Семантика NaN в IEEE754 даёт то, что он "ХЗ что", а не "значение отсутствует", что подчёркивается тем, что он не равен самому себе. Точно так же семантика того, что в SQL сказав SELECT NULL = NULL, получаешь NULL, означает, что он тоже "ХЗ что", а не "отсутствует". На "отсутствует" должно быть отдельное значение.
Как ни странно, ближе всего к этому подошли в Javascript с разделением null и undefined.
А могут быть и больше значений. В мониторинге у нас было деление на "датчик недоступен", "датчик отказал" и "датчика нет в принципе".
Соответственно, первые два давали ту вариацию null, которая не может быть в обычной семантике равна самой себе.