在Perl中,如何限制小数点后的位数,但没有尾随零?
问题描述:
这个问题类似于"dropping trailing ‘.0’ from floats",但是对于Perl和小数点后的最大位数。在Perl中,如何限制小数点后的位数,但没有尾随零?
我正在寻找一种方法来将数字转换为字符串格式,删除任何多余的'0',包括不仅在小数点后面。并且仍然具有最大数量的数字,例如3
输入数据是浮点数。所需的输出:
0 -> 0
0.1 -> 0.1
0.11 -> 0.11
0.111 -> 0.111
0.1111111 -> 0.111
答
您还可以使用Math::Round做到这一点:
$ perl -MMath::Round=nearest -e 'print nearest(.001, 0.1), "\n"'
0.1
$ perl -MMath::Round=nearest -e 'print nearest(.001, 0.11111), "\n"'
0.111
答
直接使用下列内容:
my $s = sprintf('%.3f', $f);
$s =~ s/\.?0*$//;
print $s
...或定义一个子程序做更一般:
sub fstr {
my ($value,$precision) = @_;
$precision ||= 3;
my $s = sprintf("%.${precision}f", $value);
$s =~ s/\.?0*$//;
$s
}
print fstr(0) . "\n";
print fstr(1) . "\n";
print fstr(1.1) . "\n";
print fstr(1.12) . "\n";
print fstr(1.123) . "\n";
print fstr(1.12345) . "\n";
print fstr(1.12345, 2) . "\n";
print fstr(1.12345, 10) . "\n";
打印:
0
1
1.1
1.12
1.123
1.123
1.12
1.12345
答
这会给你看你的输出g下,
sub dropTraillingZeros{
$_ = shift;
s/(\d*\.\d{3})(.*)/$1/;
s/(\d*\.\d)(00)/$1/;
s/(\d*\.\d{2})(0)/$1/;
print "$_\n";
}
dropTraillingZeros(0);
dropTraillingZeros(0.1);
dropTraillingZeros(0.11);
dropTraillingZeros(0.111);
dropTraillingZeros(0.11111111);
答
您可以使用 “的sprintf” 与 “EVAL” 组合。
my $num = eval sprintf('%.3f', $raw_num);
例如:
#!/usr/bin/perl
my @num_array = (
0, 1, 1.0, 0.1, 0.10, 0.11, 0.111, 0.1110, 0.1111111
);
for my $raw_num (@num_array) {
my $num = eval sprintf('%.3f', $raw_num);
print $num . "\n";
}
输出:
0
1
1
0.1
0.1
0.11
0.111
0.111
0.111
此解决方案仅适用于小的数字。 `print`在15位数字后全部删除小数部分或切换到科学记数法; “最接近”可以放大数字中已经存在的任何错误(例如,将`111111111129995.56`修整为`.001`与`nearest`产生`111111111129995.58`,而`sprintf(“%。3f”,111111111129995.56)`正确产生`111111111129995.56` 。) – vladr 2010-03-24 02:45:43