Как создать или проверить NaN или бесконечные значения в Perl?
Как создать или проверить NaN или бесконечность в Perl?
Ответ 1
Здесь достаточно надежный способ:
my $inf = 9**9**9;
my $neginf = -9**9**9;
my $nan = -sin(9**9**9);
sub isinf { $_[0]==9**9**9 || $_[0]==-9**9**9 }
sub isnan { ! defined( $_[0] <=> 9**9**9 ) }
# useful for detecting negative zero
sub signbit { substr( sprintf( '%g', $_[0] ), 0, 1 ) eq '-' }
for my $num ( $inf, $neginf, $nan ) {
printf("%s:\tisinf: %d,\tisnan: %d,\tsignbit: %d\n", $num, isinf($num), isnan($num), signbit($num));
}
Выход:
inf: isinf: 1, isnan: 0, signbit: 0
-inf: isinf: 1, isnan: 0, signbit: 1
nan: isinf: 0, isnan: 1, signbit: 0
Ответ 2
print "Is NaN\n" if $a eq 'nan';
print "Is Inf\n" if $a eq 'inf' or $a eq '-inf';
EDIT: исправлено для отрицательной бесконечности.
Ответ 3
Используйте Data:: Float из CPAN. Он экспортирует следующие функции:
-
float_is_infinite(
) -
float_is_nan()
- ...
И вопреки остальным полузанятым решениям, размещенным здесь, он имеет testsuite.
Ответ 4
Лично я использовал бы Math::BigFloat
(или BigInt
) для всего, что коснется бесконечности NaN
.
Зачем изобретать колесо с помощью взломанного решения, если уже есть модули, которые выполняют эту работу?
Ответ 5
Когда я искал, я получил этот сайт (здесь) и http://www.learning-perl.com/2015/05/perls-special-not-a-numbers/
Связанная статья указывает, что "nan" == "nan" никогда не является истинным, когда базовая реализация c поддерживает NaN, потому что Nan не может соответствовать себе.
Это хорошо иллюстрируется с помощью
die "This perl does not support NaN!\n" if "NaN" == "NaN";
Я предполагаю, что риск запуска вашего кода в среде, где perl ухудшился изящно, а ваш код не может быть достаточно низким, чтобы вы не слишком беспокоились.
И, конечно, если вы не хотите, чтобы perl интерполировать как число, используйте 'eq' not '=='
Ответ 6
Кратко ответьте, что работает.
1: Как создать переменную "NAN" для вывода (например, printf):
{no strict 'subs'; $NAN="NAN"+1;}
2: Как проверить "NAN" (выглядит как искусство ascii):
sub isnan {!($_[0]<=0||$_[0]>=0)}
3: Как создать переменные "INF" и INFN:
{$INF="INF"+1; $INFN=-"INF"+1}
4: Как проверить "INF" (любого знака):
sub isinf {($_[0]==+"INF")||($_[0]==-"INF")}