Информация об изменениях

Сообщение Re[2]: плавающая точка число +/-inf nan от 18.01.2023 11:19

Изменено 19.07.2023 8:19 netch80

Re[2]: плавающая точка число +/-inf nan
Здравствуйте, cppguard, Вы писали:

S>>Удобно ли что (nan == nan) == false ? Ведь партиал ордеринг звучит как излишнее усложнение...

C>Есть numbers и not-a-numbers. Для первых порядок определён полность, а вторым зачем порядок?

Например, чтобы не мучаться с тем, что нельзя даже формально сравнить два float где это надо, или отсортировать массив floatʼов.
Попробуй это сделать в Rust.

fn main() {
    let mut floats = vec![1.0, 2.0, 3.0];
    floats.sort();
    println!("{}", floats[0]);
    println!("{}", floats[1]);
    println!("{}", floats[2]);
}


Компилируем:

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 значит, что будет утвердительно выдан признак отсутствия, а что вычисления пошли неправильно, замаскируется...
Re[2]: плавающая точка число +/-inf nan
Здравствуйте, cppguard, Вы писали:

S>>Удобно ли что (nan == nan) == false ? Ведь партиал ордеринг звучит как излишнее усложнение...

C>Есть numbers и not-a-numbers. Для первых порядок определён полность, а вторым зачем порядок?

Например, чтобы не мучаться с тем, что нельзя даже формально сравнить два float где это надо, или отсортировать массив floatʼов.
Попробуй это сделать в Rust.

fn main() {
    let mut floats = vec![1.0, 2.0, 3.0];
    floats.sort();
    println!("{}", floats[0]);
    println!("{}", floats[1]);
    println!("{}", floats[2]);
}


Компилируем:

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 не определён полный порядок, и сортируют такое как хотят — выглядит дико и непривычно, приходится подставлять подпорки такие или такие.

Кстати, можешь сравнить в C++ сортировку двух массивов 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 значит, что будет утвердительно выдан признак отсутствия, а что вычисления пошли неправильно, замаскируется...