從小數格式化為指數

從小數格式化為指數

我有一個資料檔 abc.txt,格式如下:

BALT 1
 54.500 -161.070
 3.95863757
 0.01691576
BARM 2
 -9.200 67.120
 4.07529868
 0.01951653
BKSR 3
 43.830 142.520
 4.08919819
 0.00587340

我需要將其轉換為以下格式:

BALT 1
 54.5000000 -161.070000
 0.3958637E+01
 0.1691576E-01
BARM 2
 -9.20000000 67.1200000
 0.4075298E+01
 0.1951653E-01
BKSR 3
 43.8300000 142.520000
 0.4089198E+01
 0.5873400E-02

第二行中的數字所佔的總空格應為 10(不包括 -ve 符號)(例如,54.500 為 54.5000000,-161.070 為 -161.070000)。第 3 行和第 4 行的空格應為 13(例如 3.95863757 為 0.3958637E+01)。而BALT或BARM是變量,它可能是另一個具有四個字元的單字。

謝謝。

答案1

版本3使用 awk 文件,例如

function tenth(x) {
  u = x ; if ( u < 0 ) u = -x ;
  b=10 ;
  a=b-2 ;
  if ( u >= 10 ) {
  d=int(log(u)/log(10)) ;
  a=b-d-1 ;
  }
  printf "%*.*f",b,a,x ;
}
length($1) == 4 { print ; next  ;}
NF == 1 { d=int(log($1)/log(10)) ;if (d> -1) d++ ; printf " %.7fE%+03d\n",$1/(10^d),d ;}
NF == 2 { printf " " ; tenth($1); printf " " ; tenth($2) ; printf "\n" ;}

在哪裡

  • lengtht$1) == 4 { print ; next ;} 將保留第一個字段為四個字母的行(儘管可能是 1234)
  • function tenth(x):定義調整格式的函數。
  • "%*.*f"字串調整%f轉換的大小/精度。第一個 * 替換為 b,第二個 * 替換為 a。
  • int(log()/log(10))給出十進制日誌來根據您的特定需求調整表示形式?

與它一起使用

awk -f f.awk input

結果給出

BALT 1
 54.5000000 -161.070000
 0.3958638E+01
 0.1691576E-01
BALT 2
 -9.20000000 67.1200000
 0.4075299E+01
 0.1951653E-01
BALT 3
 43.8300000 142.520000
 0.4089198E+01
 0.5873400E-02
 0.00000000 1.00000000
 -3.14150000 2.71828183

答案2

也許是這樣的:

awk '
  !/[[:alpha:]]/{
    if (NF == 1)
      $0 = sprintf(" %.7E", $0 * 10)
    else
      $0 = sprintf(" %.8f %.8f", $1, $2)
  }
  {print}' | sed '
    s/\([0-9.]\{10\}\)[0-9]*/\1/g
    s/\([1-9]\)\.\(.*\).E/0.\1\2E/'

答案3

你可以在沒有 awk 的情況下得到它:

while read line; do echo $line; read a; read b; read c;  printf "%.7f %.7f\n %.7e\n %.7e\n" $a $b $c; done < data.txt

但是,如果您使用逗號而不是句點來使用某些區域設置,則以這種方式使用 printf 可能會導致一些問題。在這種情況下,您應該能夠透過以下方式修復它:

while read line; do echo $line; read a; read b; read c; LC_NUMERIC="en_US.UTF-8" printf "%.7f %.7f\n %.7e\n %.7e\n" $a $b $c; done < data.txt

當然,在腳本中,您應該使用回車和縮排來更好地格式化它。

相關內容