Проверьте, является ли переданный двойной аргумент «достаточно близким», чтобы считаться целым

0

Я работаю над кодом, где мне нужно проверить, действительно ли определенная переменная, которая может принимать двойное значение, принимает целочисленное значение. Я рассматриваю двойную переменную, которая принимает целочисленное значение, если она находится в пределах допуска целого числа. Этот допуск равен 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 профессионала.

Любые указатели будут очень благодарны!

Теги:
rounding-error

2 ответа

2
Лучший ответ

Да, с плавающей точкой сложно. Просто потому, что 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 является точным, и, следовательно, является целочисленным добавлением.

  • 0
    Ваше предложение работает в моем случае и вписывается в текущий код, который у меня есть.
2

В дополнение к hvd ответ на типы; также нецелесообразно добавлять/вычитать малые удваивания в/из больших двойников из-за того, как они внутренне представлены.

Простая работа, которая позволяет избежать обоих проблем:

if (abs(arg - round(arg)) <= SMALL) {
  return (1);
} else {
  return (0);
}
  • 0
    Похоже, что раунд не доступен в VS2010. daniweb.com/software-development/cpp/threads/270269/… но у меня есть обходной путь, как указано в этой ссылке. Ваш код работает нормально. Благодарю.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню