Сегодня я потратил около 2 часов на отслеживание ошибки, и я бы нашел ее намного быстрее, если бы java выдавала исключение при сравнении NaN с числом с плавающей запятой. Было бы неплохо, если бы я мог защитить себя от этого в будущем. Любая помощь приветствуется.
Могу ли я заставить Java выдавать исключение при сравнении между числами с плавающей запятой, когда одно из них оказывается NaN?
Ответы (2)
В справочнике по набору инструкций JVM специально запрещены байтовые коды, выполнять математику с плавающей запятой от генерации исключений и жестко указывает, как они должны работать, когда NaN является операндом. Если есть способ сделать это, вам потребуется либо явно генерировать исключения для NaN, либо использовать собственный компилятор для вставки этих проверок за вас.
Одним из вариантов, который может быть полезен, было бы написать такую функцию:
public static float check(float value) {
if (Float.isNaN(value))
throw new ArithmeticException("NaN");
return value;
}
При этом вы можете написать код для этого эффекта:
float f = check(myOtherFloat / yetAnotherFloat);
Это затем выполнит вычисления и выдаст ошибку. В идеале с коротким именем функции оно не будет слишком навязчивым.
W
Защита в float или double заключается в том, чтобы сделать результат NaN или false. Если вы хотите обнаружить NaN, вам лучше сначала предотвратить значение, например, 0/0. Когда вы выполняете деление, проверьте 0 как делитель и выдайте исключение, если это так. Вы можете обернуть это вспомогательным методом для упрощения.
public static double div(double a, double b) {
if(b == 0) throw new IllegalArguementException();
return a / b;
}
Если я знаю, что значение может быть только 0 или больше, я часто добавляю смещение, например
double d = a / (b + 1e-9);
Это никогда не дает NaN при условии, что b >= 0. Если a == 0, d == 0. Используемое смещение зависит от ситуации.