How to get bc to handle numbers in scientific (aka

2020-02-03 05:14发布

bc doesn't like numbers expressed in scientific notation (aka exponential notation).

$ echo "3.1e1*2" | bc -l
(standard_in) 1: parse error

but I need to use it to handle a few records that are expressed in this notation. Is there a way to get bc to understand exponential notation? If not, what can I do to translate them into a format that bc will understand?

9条回答
男人必须洒脱
2楼-- · 2020-02-03 05:36

Try this: (using bash)

printf "scale=20\n0.17879D-13\n" | sed -e 's/D/*10^/' | bc

or this:

 num="0.17879D-13"; convert="`printf \"scale=20\n$num\n\" | sed -e 's/D/*10^/' | bc`" ; echo $convert
.00000000000001787900
num="1230.17879"; convert="`printf \"scale=20\n$num\n\" | sed -e 's/D/*10^/' | bc`" ; echo $convert
1230.17879

If you have positive exponents you should use this:

num="0.17879D+13"; convert="`printf \"scale=20\n$num\n\" | sed -e 's/D+/*10^/' -e 's/D/*10^/' | bc`" ; echo $convert
1787900000000.00000

That last one would handle every numbers thrown at it. You can adapt the 'sed' if you have numbers with 'e' or 'E' as exponents.

You get to chose the scale you want.

查看更多
姐就是有狂的资本
3楼-- · 2020-02-03 05:41

One can use awk for this; for example,

awk '{ print +$1, +$2, +$3 }' <<< '12345678e-6 0.0314159e2 54321e+13'

produces (via awk's default format %.6g) output like
12.3457 3.14159 543210000000000000
while commands like the following two produce the output shown after each, given that file edata contains data as shown later.

$ awk '{for(i=1;i<=NF;++i)printf"%.13g ",+$i; printf"\n"}' < edata`
31 0.0312 314.15 0 
123000 3.1415965 7 0.04343 0 0.1 
1234567890000 -56.789 -30 

$ awk '{for(i=1;i<=NF;++i)printf"%9.13g ",+$i; printf"\n"}' < edata
       31    0.0312    314.15         0 
   123000 3.1415965         7   0.04343         0       0.1 
1234567890000   -56.789       -30 


$ cat edata 
3.1e1 3.12e-2 3.1415e+2 xyz
123e3 0.031415965e2 7 .4343e-1 0e+0 1e-1
.123456789e13 -56789e-3 -30

Also, regarding solutions using sed, it probably is better to delete the plus sign in forms like 45e+3 at the same time as the e, via regex [eE]+*, rather than in a separate sed expression. For example, on my linux machine with GNU sed version 4.2.1 and bash version 4.2.24, commands
sed 's/[eE]+*/*10^/g' <<< '7.11e-2 + 323e+34'
sed 's/[eE]+*/*10^/g' <<< '7.11e-2 + 323e+34' | bc -l
produce output
7.11*10^-2 + 323*10^34
3230000000000000000000000000000000000.07110000000000000000

查看更多
▲ chillily
4楼-- · 2020-02-03 05:46

Piping version of OPs accepted answer

$ echo 3.82955e-5 | sed 's/[eE]+*/\*10\^/'
3.82955*10^-5

Piping the input to the OPs accepted sed command gave extra backslashes like

$ echo 3.82955e-5 | sed 's/[eE]+*/\\*10\\^/'
3.82955\*10\^-5
查看更多
登录 后发表回答