Comments 19
Проверка на равенство double переменных в C#? Серьёзно?
+2
В каком месте вы увидели проверку на равенство double переменных?
0
if (a1[i1] < a2[i2]) {
//...
} else if (a2[i2] < a1[i1]) {
//...
} else {
// при каком условии мы сюда попадём?
}
-1
+1
public static void Main()
{
double a = 1d;
double b = 0.9999999999999999989d;
Console.WriteLine(a == b);
// Outputs: True
}
В .NET, начиная с первой версии, существует Double.Epsilon, которое используется при сравнении чисел. Но, нет гарантии, что от платформы к платформе он не будет меняться.
Да и в целом, из-за особенностей представления в памяти чисел с плавающей точкой, всегда рекомендуется производить их сравнение с явным определением точности. Это ещё на информатике в школе рассказывали.
+1
А какие есть другие варианты в этом случае? Обычное сравнение с эпсилоном ломает корректность, т.к. транзитивность.
К тому же, этот алгоритм не приводит к новым ошибкам или округлениям.
0
А что такого? Например, вполне могут быть проверки что double/float делитель не равен ровно нулю, чтобы не получить 0/0 = NaN. Или функция signum, которая очень даже отдельно рассматривает нуль.
0
Если верить исходникам то конвертируя буль в инт тернарный оператор просто прячется
0
думаю, что когда проходит jit, то эти конверсии инлайнятся, и при генерации нативного кода в стандартных местах используются bit-twiddling хаки. Ну и помогает этому то, что размер boolean такой же, как и у int32 и эта конверсия в итоге превратится на x86 машине во что-нибудь типа
cmp eax, 0
0
Несколько удивительно в таком формате от Александреску. Обычно он предлагает смотреть машинный код (что правильно), видимо тут просто лайт-версия, чтобы не травмировать нежную психику. А то ведь можно упомянуть, что у многих современных архитектур есть conditional-move (на x86, скорее всего, jit заменит ветвления на CMOVxx). Так же известно, что CMOVxx немного медленнее правильно предсказанного ветвления Jxx (по вполне рациональным причинам). И отсюда цифры в -18% и +200% становятся вполне очевидными (и даже предсказуемыми).
0
странно, что медленнее, ведь в железе это выглядит всего лишь как мультиплексор, а затраты на декодирование JXX и CMOVXX сопоставимы
0
Не могу вспомнить источник информации, но насколько я помню, при правильном предсказании ветвления команда Jxx удаляется с конвеера полностью (предсказатель ветвлений работает независимо от конвеера), а CMOVxx выполняется всегда (выполняется цикл записи), условие только выбирает куда записать результат: в точку назначения или в «пустоту».
Почему так сделано — не знаю, но наверняка для этого есть причины. Например, что просто удаляя правильно предсказанную команду Jxx нам не надо учитывать много факторов, мы просто подгружаем в конвеер данные с предполагаемого адреса, а в случае факапа в точке предполагаемого ветвления перезапускаем конвеер (привет Meltdown и Spectre).
А удаление CMOVxx завязано на переименование регистров, отложенные вычисления и Зевс знает какие ещё оптимизации. Видимо оно того не стоит.
Почему так сделано — не знаю, но наверняка для этого есть причины. Например, что просто удаляя правильно предсказанную команду Jxx нам не надо учитывать много факторов, мы просто подгружаем в конвеер данные с предполагаемого адреса, а в случае факапа в точке предполагаемого ветвления перезапускаем конвеер (привет Meltdown и Spectre).
А удаление CMOVxx завязано на переименование регистров, отложенные вычисления и Зевс знает какие ещё оптимизации. Видимо оно того не стоит.
0
А почему нельзя просто использовать switch/case, который разворачивается в branch table? Почему бы не применить loop unrolling? Это же элементарные вещи, которые не зависят от языка/компилятора.
0
Sign up to leave a comment.
Fastware