我有一个带有多个列(9列)的制表符分隔文件,如下所示:
1:21468 1 21468 2.8628817609765984 0.09640845515631684 0.05034710996552612 1.0 0.012377712911711025 54.0
然而,在第5栏中,我有时会有科学数字:
8.159959468796783E-4
8.465114165595303E-4
8.703354859736187E-5
9.05132870067004E-4
我需要在第5列中以十进制表示法包含所有数字。从上面的例子:
0.0008159959468796783
0.0008465114165595303
0.00008703354859736187
0.000905132870067004
我需要更改这些数字而不更改第5列中的其余数字或文件的其余部分。
我知道Convert scientific notation to decimal in multiple fields中有类似的帖子。但是在这种情况下,有一个if语句与字段中存在的数字类型无关,而且该字段适用于该列中的所有数字。因此,我无法将信息转换为我的具体案例。有人可以帮我解决这个问题吗?
谢谢!
答案 0 :(得分:1)
将perl中的科学符号数转换为常规符号数最简单(也是最快)的方法:
my $num = '0.12345678E5';
$num *= 1;
print "$num\n";
答案 1 :(得分:0)
如果你这样做的方法很简单,通过解析为浮点然后使用printf强制它以小数形式打印,你可能会得到稍微不同的结果,因为你处于双精度可用的精度上限 - 精确格式。
你应该做的是将每一行拆分成字段,然后用这样的东西检查字段5.
($u,$d,$exp) = $field[5] =~ /(\d)\.(\d+)[Ee]([-+]\d+)/
如果字段[5]是科学记数法,这将给你
$u the digit before the decimal
$d the digits after the decimal
$exp the exponent
(如果不是你会得到未定义的值,可以跳过重新格式化步骤)
使用该信息,您可以使用正确的前导零和小数点数重新组合数字。如果指数为正数,则必须重新组合数字,然后在正确的位置插入小数点。
按照您希望的方式重新格式化值后,重新组合整行(例如,使用join
)并将其写出来。
答案 2 :(得分:0)
正如吉姆已经提出的,一种方法是简单地将数字视为字符串并自己进行翻译。这样您就可以完全保持有效数字。
以下演示了执行此操作的功能。它接受一个可能用科学记数法表示的数字,并返回十进制表示。与正指数和负指数一起使用:
use warnings;
use strict;
while (<DATA>) {
my ($num, $expected) = split;
my $dec = sn_to_dec($num);
print $dec . ' - ' . ($dec eq $expected ? 'good' : 'bad') . "\n";
}
sub sn_to_dec {
my $num = shift;
if ($num =~ /^([+-]?)(\d*)(\.?)(\d*)[Ee]([-+]?\d+)$/) {
my ($sign, $int, $period, $dec, $exp) = ($1, $2, $3, $4, $5);
if ($exp < 0) {
my $len = 1 - $exp;
$int = ('0' x ($len - length $int)) . $int if $len > length $int;
substr $int, $exp, 0, '.';
return $sign.$int.$dec;
} elsif ($exp > 0) {
$dec .= '0' x ($exp - length $dec) if $exp > length $dec;
substr $dec, $exp, 0, '.' if $exp < length $dec;
return $sign.$int.$dec;
} else {
return $sign.$int.$period.$dec;
}
}
return $num;
}
__DATA__
8.159959468796783E-4 0.0008159959468796783
8.465114165595303E-4 0.0008465114165595303
8.703354859736187E-5 0.00008703354859736187
9.05132870067004E-4 0.000905132870067004
9.05132870067004E+4 90513.2870067004
9.05132870067004E+16 90513287006700400
9.05132870067004E+0 9.05132870067004