Я работаю над кодом, где мне нужно проверить, действительно ли определенная переменная, которая может принимать двойное значение, принимает целочисленное значение. Я рассматриваю двойную переменную, которая принимает целочисленное значение, если она находится в пределах допуска целого числа. Этот допуск равен 1e-5.
Ниже приведен мой код:
#define SMALL 1e-5
//Double that attains this is considered non zero. Strictly Less than this is 0
int check_if_integer(double arg){
//returns 1 if arg is close enough to an integer
//returns 0 otherwise
if(arg - (int)arg >= SMALL){
if(arg + SMALL > (int)(arg+1.0)){
return(1);
//Code should have reached this point since
//arg + SMALL is 16.00001
//while (int)(arg+1.0) should be 16
//But the code seems to evaluate (int)(arg+1.0) to be 17
}
}
else{
return(1);
}
return(0);
}
int main(void){
int a = check_if_integer(15.999999999999998);
}
К сожалению, при передаче аргумента 15.999999999999998 функция возвращает 0. То есть, он считает, что аргумент является дробным, в то время как он должен был вернуть 1, указывая, что аргумент "достаточно близко" до 16.
Я использую VS2010 профессионала.
Любые указатели будут очень благодарны!
Да, с плавающей точкой сложно. Просто потому, что 15.999999999999998 < 16.0
, это не значит 15.999999999999998 + 1.0 < 17.0
. Предположим, что у вас есть десятичный тип с плавающей запятой с тремя цифрами точности. Какой результат вы получаете за 9.99 + 1.0
в точности этого типа? Математический результат будет равен 10.99
, а округленная до точности этого типа дает 11.0
. Аналогичная проблема имеет двоичная с плавающей запятой.
Вы можете в данном конкретном случае изменить (int)(arg+1.0)
на (int)arg+1
. (int)arg
является точным, и, следовательно, является целочисленным добавлением.
В дополнение к hvd ответ на типы; также нецелесообразно добавлять/вычитать малые удваивания в/из больших двойников из-за того, как они внутренне представлены.
Простая работа, которая позволяет избежать обоих проблем:
if (abs(arg - round(arg)) <= SMALL) {
return (1);
} else {
return (0);
}