在PDL上向零舍入

时间:2017-06-20 11:19:19

标签: perl rounding pdl

我有一个混合值的PDL(类型double)(正面和负面)。我想将每个条目向零舍入。 因此+1.2变为+1+1.7变为+1-1.2变为-1-1.7变为-1

我想过使用int(),但它并不适用于PDL类型。

我也可以使用round(abs($x) - 0.5) * ($x <=> 0),但不确定如何在PDL上使用此逻辑。

指针?

2 个答案:

答案 0 :(得分:4)

PDL::Mathrint函数的文档说:

  

如果要将半整数从零开始舍入,请尝试floor(abs($x)+0.5)*($x<=>0)

只需稍微更改一下,使其按照您想要的方式工作:

#!/usr/bin/perl
use warnings;
use strict;

use PDL;

my $pdl = 'PDL'->new(
    [  1,  1.3,  1.9,  2,  2.1,  2.7 ],
    [ -1, -1.3, -1.9, -2, -2.1, -2.7 ]
);
$pdl = floor(abs($pdl)) * ($pdl <=> 0);
print $pdl;

输出:

[
 [ 1  1  1  2  2  2]
 [-1 -1 -1 -2 -2 -2]
]

答案 1 :(得分:1)

PDL::Mathfloorceilrint。所有这些功能都有效。

因此,以下内容应该有效:

#!/usr/bin/env perl
use warnings;
use strict;

use PDL;

my $pdl = 'PDL'->new(
    [  1,  1.3,  1.9,  2,  2.1,  2.7 ],
    [ -1, -1.3, -1.9, -2, -2.1, -2.7 ]
);

print $pdl;

floor(inplace $pdl->where($pdl >= 0));
ceil (inplace $pdl->where($pdl <  0));

print $pdl;

输出:

[
 [   1  1.3  1.9    2  2.1  2.7]
 [  -1 -1.3 -1.9   -2 -2.1 -2.7]
]

[
 [ 1  1  1  2  2  2]
 [-1 -1 -1 -2 -2 -2]
]

PS:@ choroba的答案似乎在以下基准测试中运行速度提高了约20%,an ancient MacBook Pro上的非线程perl 5.24:

#!/usr/bin/env perl
use warnings;
use strict;

use constant N_ELEMS => $ARGV[0] || 100_000;

use Dumbbench;
use PDL;

sub one_scan {
    my $pdl = 100 * grandom(N_ELEMS);
    $pdl = floor(abs($pdl)) * ($pdl <=> 0);
    return;
}

sub two_scans {
    my $pdl = 100 * grandom(N_ELEMS);
    floor(inplace $pdl->where($pdl >= 0));
    ceil (inplace $pdl->where($pdl <  0));
    return;
}

sub baseline {
    my $pdl = 100 * grandom(N_ELEMS);
    return;
}

my $bench = Dumbbench->new;

$bench->add_instances(
    Dumbbench::Instance::PerlSub->new(code => \&baseline,  name => 'Baseline'),
    Dumbbench::Instance::PerlSub->new(code => \&one_scan,  name => 'One Scan'),
    Dumbbench::Instance::PerlSub->new(code => \&two_scans, name => 'Two Scans'),
);

$bench->run;
$bench->report;