回答:
でbash
、それはおそらくそれと同じくらい良いです。それはシェル組み込みを使用します。変数に結果が必要な場合は、コマンド置換またはbash
特定のコマンドを使用できます(ただし、現在はでもサポートされていますzsh
)。
printf -v int %.0f "$float"
できること:
float=1.23
int=${float%.*}
しかし、それはあなたに最も近い整数を与える代わりに小数部分を削除するでしょう、そして、それは$float
like 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))"
(下記参照)。
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,2
にprint 1, 2
2つの引数を渡すのと同じですprint
)
でzsh
(小数点セパレータは常に期間)である浮動小数点演算をサポート()は、次のものがrint()
フロートとして(のようにあなたに最も近い整数を与える数学関数C
)とint()
(のようフロートからあなたの整数を与えるためにawk
)。だからあなたができる:
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
または:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
ただし、double
sは非常に大きな数を表すことができますが、整数ははるかに制限されていることに注意してください。
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
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)スクリプトで非常にうまく機能しました。
,
10進数として持っています。セクションを参照してくださいLC_ALL=C
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
float=-2; echo "($float+0.5)/1" | bc
与える-1
。
関連する:
@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] )}' "$@";
}
printf
動作と異なるのか、またはbuiltinよりawkを好む他の理由があるのかはわかりませんprintf
。