if (isValid(s))
cout << s << " - допустимое число одинарной точности." << endl;
else
cout << s << " - HE допустимое число одинарной точности " << endl;
}
int main() {
test("12345");
test("1.23456");
test("-1.23456");
test(" - 1.23456");
test("+1.23456");
test(" 1.23456 ");
test("asdf");
}
Вот вывод этого примера.
12345 - допустимое целое число.
12345 - допустимое число двойной точности.
12345 - допустимое число одинарной точности.
1.23456 - НЕ допустимое целое число.
1.23456 - допустимое число двойной точности.
1.23456 - допустимое число одинарной точности.
-1.23456 - НЕ допустимое целое число.
-1.23456 - допустимое число двойной точности.
-1.23456 - допустимое число одинарной точности.
- 1.23456 - НЕ допустимое целое число.
- 1 23466 - НЕ допустимое число двойной точности.
- 1.23456 - НЕ допустимое число одинарной точности.
+1.23456 - НЕ допустимое целое число.
+1.23456 - допустимое число двойной точности.
+1.23456 - допустимое число одинарной точности.
1.23456 - НЕ допустимое целое число.
1.23456 - НЕ допустимое число двойной точности.
1.23456 - НЕ допустимое число одинарной точности.
asdf - НЕ допустимое целое число.
asdf - НЕ допустимое число двойной точности.
asdf - НЕ допустимое число одинарной точности.
Обсуждение
Шаблон функции lexical_castпреобразует значение из одного типа в другой. Он объявлен следующим образом.
template
Target lexical_cast(Source arg)
Source— это тип оригинальной переменной, a Target — это тип переменной, в которую значение преобразуется. Таким образом, например, чтобы преобразовать из stringв int, вызов lexical_castимеет вид:
int i = lexical_cast(str); // str - это строка
lexical_castпроводит анализ и пытается выполнить преобразование. Если преобразование невозможно, он выбрасывает исключение bad_lexical_cast. В примере 3.5 я только хочу проверить допустимость, и мне не требуется сохранять целевую переменную, так что если исключение не выбрасывается, я возвращаю true, а в противном случае — false.
В lexical_castтребуется передать только первый аргумент, поскольку это шаблон, что означает, что компилятор может догадаться, какой тип имеет аргумент функции, и использовать его в качестве второго аргумента. Пояснение этой ситуации более сложно, чем простая демонстрация, так что позвольте мне использовать фрагмент кода примера. Вместо того чтобы вызывать lexical_cast, как в предыдущем фрагменте кода, можно сделать так.
int i = lexical_cast(str);
Это означает то же самое, но указывать аргумент stringне требуется, так как компилятор видит, что str— это string, и понимает, что от него требуется дальше.
Если вы собираетесь написать аналогичную функцию-обертку для проверки допустимости, возвращающую trueи false, ее также можно написать как шаблон функции. В этом случае ее потребуется написать только один раз с использованием параметризованного типа, а различные версии будут генерироваться при каждом ее использовании с различными типами.
lexical_castтакже удобен для преобразования из одного числового типа в другой. Более подробно это обсуждается в рецепте 3.6.
Смотри также
Рецепт 3.6.
3.4. Сравнение чисел с плавающей точкой с ограниченной точностью
Проблема
Требуется сравнить значения с плавающей точкой, но при этом выполнить сравнение на равенство, больше чем или меньше чем с ограниченным количеством десятичных знаков. Например, требуется, чтобы 3.33333 и 3.33333333 считались при сравнении с точностью 0.0001 равными.
Решение
Напишите свои функции сравнения, которые принимают в качестве параметра ограничение точности сравнения. Пример 3.6 показывает основную методику, используемую в такой функции сравнения.
Пример 3.6. Сравнение чисел с плавающей точкой
#include
#include // для fabs()
using namespace std;
bool doubleEquals(double left, double right, double epsilon) {
return (fabs(left - right) < epsilon);
}
bool doubleLess(double left, double right, double epsilon,
bool orequal = false) {
if (fabs(left - right) < epsilon) {
// В рамках epsilon, так что считаются равными
return (orequal);
}
return (left < right);
}
bool doubleGreater(double left, double right, double epsilon,
Читать дальше