浮動小数点数を整数に変換する方法は?


47

これはbashで整数から浮動小数点への変換を行う正しい方法ですか?他の方法はありますか?

flotToint() {
    printf "%.0f\n" "$@"
}

5
「正しい」とは何ですか?
ジョセフR.

確認したいだけです..これは正しいですか、これよりも良いですか?
ラーフルパティル

2
%.0f切り上げまたは切り捨てられます。それはあなたが望むものですか?printf "%d\n" "$@" 2>/dev/null分数を切り刻むために使用できます。
ott--

回答:


70

バッシュ

bash、それはおそらくそれと同じくらい良いです。それはシェル組み込みを使用します。変数に結果が必要な場合は、コマンド置換またはbash特定のコマンドを使用できます(ただし、現在はでもサポートされていますzsh)。

printf -v int %.0f "$float"

できること:

float=1.23
int=${float%.*}

しかし、それはあなたに最も近い整数を与える代わりに小数部分を削除するでしょう、そして、それは$floatlike 1.2e9または.12例えばの値に対しては機能しません。

また、floatの内部表現による制限の可能性にも注意してください。

$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560

整数を取得しますが、その整数をどこでも使用できない可能性があります。

また、@ BinaryZebraで述べられているように、いくつかのprintf実装(bash、ksh93、yash、GNU、zsh、dashではない)では、ロケール(.またはorの可能性がある小数点区切り記号)の影響を受けます,

したがって、フロートが常に小数点を小数点としてピリオドで表され、printfスクリプトを呼び出すユーザーのロケールに関係なく浮動小数点として処理されるようにするには、ロケールをCに修正する必要があります。

LC_ALL=C printf '%.0f' "$float"

ではyash、次のこともできます。

printf '%.0f' "$(($float))"

(下記参照)。

POSIX

printf "%.0f\n" 1.1

POSIX %fでサポートする必要がないため、POSIXではありません。

POSIXly、次のことができます:

f2i() {
  awk 'BEGIN{for (i=1; i<ARGC;i++)
   printf "%.0f\n", ARGV[i]}' "$@"
}

その1つはロケールの影響を受けません(コンマはawkそこの構文ですでに特殊文字なので、コンマは小数点区切りにできません(print 1,2print 1, 22つの引数を渡すのと同じですprint

zsh

zsh(小数点セパレータは常に期間)である浮動小数点演算をサポート()は、次のものがrint()フロートとして(のようにあなたに最も近い整数を与える数学関数C)とint()(のようフロートからあなたの整数を与えるためにawk)。だからあなたができる:

$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123

または:

$ integer i=$((rint(5.678e2)))
$ echo $i
568

ただし、doublesは非常に大きな数を表すことができますが、整数ははるかに制限されていることに注意してください。

$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808

ksh93

ksh93は、浮動小数点演算をサポートする最初のBourne風のシェルでした。ksh93は、コマンドが組み込みコマンドのみである場合、パイプまたはフォークを使用しないことにより、コマンド置換を最適化します。そう

i=$(printf '%.0f' "$f")

フォークしません。またはさらに良い:

i=${ printf '%.0f' "$f"; }

分岐もしませんが、偽のサブシェル環境を作成するという面倒なこともありません。

次のこともできます。

i=$((rint(f)))

ただし、次のことに注意してください。

$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19

次のこともできます。

integer i=$((rint(f)))

しかしzsh

$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808

ksh93浮動小数点演算は、ロケールの小数点の設定を尊重することに注意してください(,それ以外の場合は数学演算子です($((1,2))フランス語/ドイツ語...ロケールでは6/5 $((1, 2))、英語ロケールでは2 と同じ)。 。

ヤシュ

yashは浮動小数点演算もサポートしていますが、ksh93/ zshのような数学関数はありませんrint()。ただし、バイナリまたは演算子を使用することで、数値を整数に変換できます(でも機能しますzshが、機能しませんksh93)。ただし、小数部分は切り捨てられ、最も近い整数は得られないことに注意してください。

$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808

yash 出力でロケールの小数点を尊重しますが、算術式の浮動小数点リテラル定数は無視します。

$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator

ピリオドを使用するスクリプトで浮動小数点定数を使用でき、他のロケールで動作を停止することを心配する必要はありませんが、それでもユーザーが表現する数値を処理できるという点で優れています覚えているとおり:

var=$((10.3)) # and not var=10.3
... "$((a + 0.1))" # and not "$(($a + 0.1))".

printf '%.0f\n' "$((10.3))" # and not printf '%.0f\n' 10.3

int=${float%.*}Mac(バージョン10.13.4(17E199))上のbash(バージョン3.2.57(1)-release)スクリプトで非常にうまく機能しました。
TelamonAegisthus

あなた最初の製剤は、例えば、GNUのbashの4.4.19に失敗: `` `$エコー$最大32.800 $ printfの-v int型%.0f "$最大"のbash:printf関数:32.800:無効な数の` ``
ルイス・デ・スーザ

@LuísdeSousa、あなたのロケールはおそらく,10進数として持っています。セクションを参照してくださいLC_ALL=C
ステファンChazelas

(注)この答えは別の質問に答えること:ドットの後の数字を削除する方法:頼まれたではないものをの整数にfloatを行う方法を
アイザック

このメソッドは、任意のビット数のフロートに適用する必要がありますか?23ビットまたは128ビット仮数の浮動小数点数でも同じになりますか?
アイザック

21

bc -任意精度の計算機言語

int(float)は次のようになります。

$ echo "$float/1" | bc 
1234

これをより良く丸めるには:

$ echo "($float+0.5)/1" | bc 

例:

$ float=1.49
$ echo "($float+0.5)/1" | bc 
1
$ float=1.50
$ echo "($float+0.5)/1" | bc 
2

4
しかし、float=-2; echo "($float+0.5)/1" | bc与える-1
ステファンシャゼル14

2
これは+ infへのラウンドと呼ばれます。それは4つの可能な方法の 1つです。

5

提出された以前の回答はほぼ正しかったです:「あなたはできる:

float=1.23
int=${float%.*}

しかし、それはあなたに最も近い整数を与える代わりに小数部分を削除し、例えば1.2e9や.12のような$ floatの値に対しては機能しません。... "

使用するだけ${float%%.*}です。

echo ${float%%.*}
1

3

非常にシンプルなハッキーなものは

function float_to_int() { 
  echo $1 | cut -d. -f1    # or use -d, if decimals separator is ,
}

サンプル出力

$ float_to_int 32.333
32
$ float_to_int 32
32

を使用することも可能ですsedが、cut解決策は簡単です。私は好むsedか、cut彼らがより組み込みターゲット上の私見は、より利用できるようawk(経由まだかなり一般的であるbusyboxよりもbc)。
ペビック

0

関連する:

  1. awk整数を浮動小数点にする方法
  2. シェルで浮動小数点数を丸める方法は?

@StéphaneChazelasの awk回答を補完する:

float_to_integer_rounding_nearst() {
    awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%.0f", ARGV[i]}' "$@";
}

float_to_integer_rounding_floor() {
    awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%d", int( ARGV[i] )}' "$@";
}

私のawksでは、後者はマイナスの無限大ではなくゼロに向かって丸められます(「床」を意味すると解釈できるため)。また、最初のラウンドは偶数に半分になります。それがBashのprintf動作と異なるのか、またはbuiltinよりawkを好む他の理由があるのか​​はわかりませんprintf
イルカチュウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.