Некоторые числа (например, 6.65) имеют точное представление в десятичном виде, но не могут быть точно представлены в двоичной с плавающей запятой, которую используют компьютеры (точно так же, как 1/3 не имеет точного десятичного представления). В результате числа с плавающей запятой часто немного отличаются от ожидаемых. Результат вашего расчета не 3, а около 3.000000000000000444.
Традиционный способ справиться с этим - определить небольшое число (называемое эпсилон), а затем считать два числа равными, если они отличаются меньше, чем эпсилон.
Ваше решение ceil("$n")
работает, потому что Perl округляет число с плавающей запятой примерно до 14 десятичных знаков при преобразовании его в строку (таким образом, преобразовывая 3.000000000000000444 обратно в 3). Но более быстрое решение состоит в том, чтобы вычесть эпсилон (поскольку округляется ceil
) до вычисления ceil
:
my $epsilon = 5e-15; # Or whatever small number you feel is appropriate
my $c = ceil($n - $epsilon);
Вычитание с плавающей запятой должно быть быстрее, чем преобразование в строку и обратно (что включает в себя большое деление).