0

我有一个double混合值(正数和负数)的 PDL(类型)。我想将每个条目四舍五入为零。所以+1.2变成+1+1.7变成+1-1.2变成,变成-1-1.7变成-1

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

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

指针?

4

2 回答 2

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]
]
于 2017-06-20T11:42:34.133 回答
1

PDL::Mathfloor,ceilrint. 所有这些功能都可以正常工作。

因此,应该像下面这样工作:

#!/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%,在古代 MacBook Properl上使用非线程 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;
于 2017-06-20T11:23:18.767 回答