Как проверить целое ли число c
Перейти к содержимому

Как проверить целое ли число c

Как определить, целое ли число?

user avatar

Давно C++ не использовал, но на сколько я помню такие вещи делаются через оператор привидения типов:

Все другие привидения — это что-то унаследованное от С . В С++ для каждого случая есть свой оператор.

Для проверки встроенных типов данный подход не подойдет. В различных компиляторах есть макросы, например, __typeof__ . Они специфичны для конкретного компилятора.

C++ Поддерживает урезанный RTTI. Возможно использовать только языковые возможности C++ , посмотрите на этот код:

user avatar

Лучше всегда использовать double (float только для хранения в больших массивах).

Для этого надо подключить math.h.

Некоторые могут возразить, что сравнивать числа с плавающей запятой на равенство неправильно. Но если бы это было неправильно всегда, компилятор бы такое в принципе не позволял. В данном случае целые числа могут быть представлены точно в double. Операции сложения, вычитания и умножения для целых чисел также дадут целые числа, так как не вносят погрешностей округления. Для чисел, заданных вручную или полученных таким способом, проверка выше сработает корректно. Если всё же нужно проверить, что число целое в пределах некоторой погрешности eps (например 0.000001), можно использовать следующую проверку:

Или если в используемой версии стандартной библиотеки доступна функция round:

Эти два варианта используют округление к ближайшему целому, чтобы разность между этим и исходным числом была в интервале (-0.5; 0.5], а не [0; 1), как в случае округления к меньшему.

c++ как проверить,является ли число целым?

int _tmain()
<
double b = 2.345034;
double c = b — (int)b;
if(c > 0)
<
cout << «Число не целое»;
>
else
<
cout << «Число целое»;
>
>
вместо b может быть любое другое число. либо можно вообще как функцию оформить

В некоторых случаях это невозможно, так как добные числа записываются в спец-формате, и, например, число 0.7 это на самом деле 0.6999999999.
В результате
double a = 10*(0.1 + 0.7);
int b = int(a); // в b у нас лежит 7, а не 8, как можно было ожидать

Поэтому, обычно сравнивают как

abs((valA — valB)) < epsilon;

где epsilon, например, равен 0.0000001

Соответственно, если мы сравниваем число и округленное число, и они равны, то можно с определенной долей вероятности утверждать, что в нашей переменной с плавающей точкой находится целое число

То есть мы сравниваем, что два числа очень близки, а не то что они равны.

Как проверить целое ли число c

Здравствуйте, Аноним, Вы писали:

А>и подвопросик — как отрезать дробную часть?

От: Аноним
Дата: 20.04.06 08:31
Оценка:

Здравствуйте, Аноним, Вы писали:

А>и подвопросик — как отрезать дробную часть?

В каком представлении у тебя число?
Строка, double, или вообще что-то другое?

От: piAnd
Дата: 20.04.06 08:45
Оценка:
От: Mickey_from_nsk
Дата: 20.04.06 09:17
Оценка:
От: FoolS.Top
Дата: 20.04.06 09:20
Оценка:
От: Аноним
Дата: 20.04.06 09:30
Оценка:
От: Pavel Dvorkin
Дата: 20.04.06 09:46
Оценка:

Здравствуйте, Аноним, Вы писали:

Прочитал все ответы. Все они некорректны ИМХО.

Во-первых, число может оказаться , скажем, 19.9999999999999. Оно целое или нет ? А если да, то сколько из него надо вычесть, чтобы оно стало нецелым ? 19.999999999999 — еще целое ? А 19.99999999999 ? А это ведь ошибка представления в двоичной системе, всего лишь.

Во-вторых, преобразование к int может банально не пройти из-за диапазона значений.

float a = 1E35; // и как Вы это в int преобразуете ?

На мой взгляд, единственно, что возможно

1. Определить понятие целого вещественного числа. Т.е. считать его целым, если оно отличается от ближайшего целого не более, чем на eps, которое надо установить волевым путем.
2. После того, как это определено, преобразовать это число в строку (sprintf(s,»%f», a) и провести анализ строки. Упражнение для олимпиад по программированию среди школьников.

От: Mickey_from_nsk
Дата: 20.04.06 10:03
Оценка:

Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Прочитал все ответы. Все они некорректны ИМХО.
Логично. Сильной философии тут не разводили. Так, жизненные проблемы решали.

PD>Во-первых, число может оказаться , скажем, 19.9999999999999. Оно целое или нет ? А если да, то сколько из него надо вычесть, чтобы оно стало нецелым ? 19.999999999999 — еще целое ? А 19.99999999999 ? А это ведь ошибка представления в двоичной системе, всего лишь.
А ты можешь гарантировать, что это ошибка? Может это намеренное искажение?

PD>Во-вторых, преобразование к int может банально не пройти из-за диапазона значений.
Может и не пройти. Но можно число «запихнуть» в нужный диапазон.
PD>float a = 1E35; // и как Вы это в int преобразуете ?
Получим overflow, ясен пень — не целое

PD>На мой взгляд, единственно, что возможно

PD>1. Определить понятие целого вещественного числа. Т.е. считать его целым, если оно отличается от ближайшего целого не более, чем на eps, которое надо установить волевым путем.
PD>2. После того, как это определено, преобразовать это число в строку (sprintf(s,»%f», a) и провести анализ строки. Упражнение для олимпиад по программированию среди школьников.
Или такой вариант — выдать на экран и спросить у пользователя.

Без обид — все можно раскритиковать. Везде можно поставить массу условий при которых работать все равно не будет. (в твоем примере тоже, как многие говорят, лучше snprintf использовать или ostringstream).
Даем варианты, другим — выбирать.

От: Pavel Dvorkin
Дата: 20.04.06 10:09
Оценка:

Здравствуйте, Mickey_from_nsk, Вы писали:

PD>>Во-первых, число может оказаться , скажем, 19.9999999999999. Оно целое или нет ? А если да, то сколько из него надо вычесть, чтобы оно стало нецелым ? 19.999999999999 — еще целое ? А 19.99999999999 ? А это ведь ошибка представления в двоичной системе, всего лишь.
M__>А ты можешь гарантировать, что это ошибка? Может это намеренное искажение?

Я же ясно пишу — понятие целого вещественного числа не определено.

PD>>float a = 1E35; // и как Вы это в int преобразуете ?
M__>Получим overflow, ясен пень — не целое

Почему ? 1E35 очень даже целое.

PD>>1. Определить понятие целого вещественного числа. Т.е. считать его целым, если оно отличается от ближайшего целого не более, чем на eps, которое надо установить волевым путем.
PD>>2. После того, как это определено, преобразовать это число в строку (sprintf(s,»%f», a) и провести анализ строки. Упражнение для олимпиад по программированию среди школьников.
M__>Или такой вариант — выдать на экран и спросить у пользователя.

Тоже годится . Но я все же предложил програмный путь.

M__>Без обид — все можно раскритиковать. Везде можно поставить массу условий при которых работать все равно не будет. (в твоем примере тоже, как многие говорят, лучше snprintf

Не обязательно. Если размер буфера == 100, выйти за его пределы невозможно.

От: Mickey_from_nsk
Дата: 20.04.06 10:17
Оценка:
От: Аноним
Дата: 20.04.06 10:37
Оценка:

А>>>и подвопросик — как отрезать дробную часть?

А>>В каком представлении у тебя число?
А>>Строка, double, или вообще что-то другое?
А>ну на самом деле с float можно применить варианты выше. А вот с double такой врядтле прокатит.

А в чем принципиальная разница между float и double

А> Лично я использую float и именно такой способ как написан выше. Мне интересно есть ли ещё варианты

Ничего не понимаю

От: HiSH http://m0riarty.ya.ru
Дата: 20.04.06 10:41
Оценка:

Здравствуйте, Mickey_from_nsk, Вы писали:

PD>>Тоже годится . Но я все же предложил програмный путь.
M__>Ну кстати, анализ тогда можно свести к поиску десятичной точки

1e6 и 1e-6 — оба не содержат десятичной точки

От: SWW
Дата: 20.04.06 10:42
Оценка:

PD>Прочитал все ответы. Все они некорректны ИМХО.

не уверен

PD>Во-первых, число может оказаться , скажем, 19.9999999999999. Оно целое или нет ?

Нет. Вопрос был, как отрезать дробную часть. Здесь она 0.9999999999999, а целая — 19

PD> А если да, то сколько из него надо вычесть, чтобы оно стало нецелым ? 19.999999999999 — еще целое ? А 19.99999999999 ? А это ведь ошибка представления в двоичной системе, всего лишь.

Если бы надо было округлить — именно так и спросили бы.

PD>Во-вторых, преобразование к int может банально не пройти из-за диапазона значений.
PD>float a = 1E35; // и как Вы это в int преобразуете ?

У floor() такой проблемы нет.

PD>На мой взгляд, единственно, что возможно
PD>1. Определить понятие целого вещественного числа. Т.е. считать его целым, если оно отличается от ближайшего целого не более, чем на eps, которое надо установить волевым путем.
PD>2. После того, как это определено, преобразовать это число в строку (sprintf(s,»%f», a) и провести анализ строки. Упражнение для олимпиад по программированию среди школьников.

От: Erop
Дата: 20.04.06 10:56
Оценка:

Здравствуйте, Pavel Dvorkin, Вы писали:

PD>На мой взгляд, единственно, что возможно
PD>1. Определить понятие целого вещественного числа. Т.е. считать его целым, если оно отличается от ближайшего целого не более, чем на eps, которое надо установить волевым путем.
PD>2. После того, как это определено, преобразовать это число в строку (sprintf(s,»%f», a) и провести анализ строки. Упражнение для олимпиад по программированию среди школьников.

Я согласен, что задача некорректная. Так что хотят на самом деле не понятно. Так что не понятно и какой ответ про 1e35 правильный, например и про 5 — DBL_EPS тоже

Но что мнея порадовало, так этоп редложение анализировать строку.
Может проще всё-таки само число?

От: Mickey_from_nsk
Дата: 20.04.06 10:56
Оценка:
От: Кодт
Дата: 20.04.06 10:59
Оценка: 1 (1)

Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Во-первых, число может оказаться , скажем, 19.9999999999999. Оно целое или нет ? А если да, то сколько из него надо вычесть, чтобы оно стало нецелым ? 19.999999999999 — еще целое ? А 19.99999999999 ? А это ведь ошибка представления в двоичной системе, всего лишь.

PD>Во-вторых, преобразование к int может банально не пройти из-за диапазона значений.

PD>float a = 1E35; // и как Вы это в int преобразуете ?

Во-первых, есть диапазон целых чисел, представимых с помощью float / double. Это те, чья разрядность равна разрядности мантиссы (минус один недостоверный разряд).
20 — представимое. Поэтому 19.99999 — это всё-таки не 20 ровно, а 20-eps. Нужно знать природу этого eps, прежде чем говорить.
Потому что

Вот если бы взяли число 1.99999999e10f — 2*10^10 ещё влезает в int, но уже вылезло из мантиссы float. Оно непредставимо, и здесь мы неизбежно имеем дело с погрешностью.

PD>На мой взгляд, единственно, что возможно

PD>1. Определить понятие целого вещественного числа. Т.е. считать его целым, если оно отличается от ближайшего целого не более, чем на eps, которое надо установить волевым путем.

Какой-такой волевой путь?

Любому значению соответствует некоторая погрешность конкретно этого значения — связанная не только с ошибками представления, но и с ошибками ввода, ошибками вычислений и т.д.
Эти погрешности рассчитываются, а не берутся с потолка.
Если трассировать погрешности всех значений проблематично — то можно сделать оценку сверху, т.е. загрубить конечный результат.

И вот тогда, для значения (x,eps) представляющего «нечто в диапазоне (x-eps,x+eps)» можно говорить, что оно ещё и представляет некое целое число, попавшее в этот диапазон. Хорошо, если это число одно.

PD>2. После того, как это определено, преобразовать это число в строку (sprintf(s,»%f», a) и провести анализ строки. Упражнение для олимпиад по программированию среди школьников.

Для извращенцев.
Хотя бы потому, что sprintf переводит в десятичную запись и тем самым вносит дополнительные погрешности.

От: Pavel Dvorkin
Дата: 20.04.06 12:08
Оценка:

Здравствуйте, Erop, Вы писали:

E>Но что мнея порадовало, так этоп редложение анализировать строку.
E>Может проще всё-таки само число?

Теперь понял, за что ты смайлик поставил
Можно и число, но, боюсь, дело кончится ассемблером с анализом битового представления формата плавающих чисел. Потому что есть float, есть double, есть (пусть и нет его в VC) long double. А как иначе — я с трудом представляю. Расскажи, если знаешь как.

От: Pavel Dvorkin
Дата: 20.04.06 12:20
Оценка:

Здравствуйте, Кодт, Вы писали:

К>Во-первых, есть диапазон целых чисел, представимых с помощью float / double. Это те, чья разрядность равна разрядности мантиссы (минус один недостоверный разряд).

+1

К>20 — представимое. Поэтому 19.99999 — это всё-таки не 20 ровно, а 20-eps. Нужно знать природу этого eps, прежде чем говорить.
К>Потому что
К>

В этом виде природа eps определяется исходя из формата представления чисел IEEE (номер не помню). И, естественно, eps зависит от абсолютной величины числа.

PD>>На мой взгляд, единственно, что возможно

PD>>1. Определить понятие целого вещественного числа. Т.е. считать его целым, если оно отличается от ближайшего целого не более, чем на eps, которое надо установить волевым путем.

К>Какой-такой волевой путь?

К>Любому значению соответствует некоторая погрешность конкретно этого значения — связанная не только с ошибками представления, но и с ошибками ввода, ошибками вычислений и т.д.
К>Эти погрешности рассчитываются, а не берутся с потолка.

Вот здесь не соглашусь. Есть еще погрешности входных данных. Они определяются не математикой, а точностью прибора и т.д. Так что числа, полученные из эксперимента, можно считать целыми (если это кому-то нужно), только в том случае, когда они отличаются от математического целого не более чем на эту погрешность эксперимента. Это и есть то, что я хотел сказать, говоря о волевом пути. К примеру, вес любого предмета в граммах, полученный с помощью магазинных весов, есть число целое всегда — эти весы доли грамма не дают. Поэтому можно считать целым любой вес в граммах, полученный таким образом. То же численно значение веса, полученное с помощью аналитических весов, целым не будет. Так что в реальной задаче eps определяется все же именно из самой задачи (волевым путем).

Иными словами, эти погрешности определяются еще и нематематическим фактором.

К>Если трассировать погрешности всех значений проблематично — то можно сделать оценку сверху, т.е. загрубить конечный результат.

К>И вот тогда, для значения (x,eps) представляющего «нечто в диапазоне (x-eps,x+eps)» можно говорить, что оно ещё и представляет некое целое число, попавшее в этот диапазон. Хорошо, если это число одно.

PD>>2. После того, как это определено, преобразовать это число в строку (sprintf(s,»%f», a) и провести анализ строки. Упражнение для олимпиад по программированию среди школьников.

К>Для извращенцев.
К>Хотя бы потому, что sprintf переводит в десятичную запись и тем самым вносит дополнительные погрешности.

Предложи что-то иное. Я кроме анализа битов двоичного представления ничего не вижу.

От: Pavel Dvorkin
Дата: 20.04.06 12:24
Оценка:

Здравствуйте, SWW, Вы писали:

PD>>Прочитал все ответы. Все они некорректны ИМХО.

SWW>не уверен

PD>>Во-первых, число может оказаться , скажем, 19.9999999999999. Оно целое или нет ?

SWW>Нет. Вопрос был, как отрезать дробную часть. Здесь она 0.9999999999999, а целая — 19

Это есть десятичное представление двоичного числа. Представление такое в общем случае точным быть не может. Так что если это 19.9999999999999 получилось в результате расчета, вполне возможно, это 20.0000000000001. А делать серьезный вывод ( 19 или 20, .9999999999999 или .000000000001) уж точно не стоит.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *