Если вы хотите округлить с произвольной точностью, а вашему методу округления не хватает контроля точности, это должно сработать:
По крайней мере, в Perl мод должен быть быстрее
Вот почему:
Образец (10 ** 7) * 3 случайных чисел сгенерировал этот тест:
Dividing
Time taken was 7 wallclock secs ( 6.83 usr 0.00 sys + 0.00 cusr 0.00 csys = 6.83 CPU) seconds
Multiplying
Time taken was 7 wallclock secs ( 6.67 usr 0.00 sys + 0.00 cusr 0.00 csys = 6.67 CPU) seconds
Modding
Time taken was 8 wallclock secs ( 7.87 usr 0.00 sys + 0.00 cusr 0.00 csys = 7.87 CPU) seconds
Multiply + Dividing
Time taken was 10 wallclock secs (10.18 usr 0.01 sys + 0.00 cusr 0.00 csys = 10.19 CPU) seconds
Обратите внимание, что 10 ** 7 * 3
- это REDICULOUS число операций с плавающей запятой. Я не мог использовать 10**8
с плавающей точкой, потому что для честного теста мне пришлось использовать одну и ту же последовательность с плавающей точкой для всех тестов, и это число с плавающей точкой исчерпало мой 4G памяти
Хорошо, побочная тема: /
(Реализация Perl использует только Int, который усекается вместо обычного округления)
use strict;
use warnings;
use version;
our $VERSION = qv('0.1');
sub xround {
my ( $number, $precision ) = @_ ;
if ( $precision eq 0 )
{
return int( $number + .5 );
}
my $scale = 10 ** abs( $precision ) ;
$number = $number / $scale if $precision > 0;
$number = $number * $scale if $precision < 0;
$number = int( $number + .5 );
$number = $number * $scale if $precision > 0;
$number = $number / $scale if $precision < 0;
return $number;
}
my $fmt = "%s : %s ( %s )\n";
my $n = 55555.55555;
for my $i ( -4 .. 4 )
{
printf $fmt, $n, xround($n, $i), $i;
}
.
55555.55555 : 55555.5556 ( -4 )
55555.55555 : 55555.556 ( -3 )
55555.55555 : 55555.56 ( -2 )
55555.55555 : 55555.6 ( -1 )
55555.55555 : 55556 ( 0 )
55555.55555 : 55560 ( 1 )
55555.55555 : 55600 ( 2 )
55555.55555 : 56000 ( 3 )
55555.55555 : 60000 ( 4 )
с использованием метода модуля
Это работает так же, как описано выше, (кроме округления), используя метод модуля для целых чисел, но все еще работает для округления до точности с плавающей запятой (с небольшим замедлением для точности справа от десятичной точки.
use strict;
use warnings;
use version;
our $VERSION = qv('0.1');
sub xround {
my ( $number, $precision ) = @_;
my $ino = int( $number );
if ( $precision eq 0 ) {
return $ino;
}
my $power = 10**$precision;
if ( $precision > 0 ) {
return int( $number - ( $number % $power ) );
}
return $ino + int( ( $number - $ino ) / $power ) * $power;
}
my $fmt = "%s : %s ( %s )\n";
my $n = 55555.55555;
for my $i ( -4 .. 4 )
{
printf $fmt, $n, xround($n, $i), $i;
}
.
55555.55555 : 55555.5555 ( -4 )
55555.55555 : 55555.555 ( -3 )
55555.55555 : 55555.55 ( -2 )
55555.55555 : 55555.5 ( -1 )
55555.55555 : 55555 ( 0 )
55555.55555 : 55550 ( 1 )
55555.55555 : 55500 ( 2 )
55555.55555 : 55000 ( 3 )
55555.55555 : 50000 ( 4 )