これはbashで浮動小数点を整数に変換する正しい方法ですか?別の方法がありますか?
flotToint() {
printf "%.0f\n" "$@"
}
答え1
強く打つ
ではbash
これはすでに最高かもしれません。シェル組み込み関数を使用します。変数に結果が必要な場合は、コマンドの置き換えまたはbash
特定のコマンドを使用できます(現在もサポートされていますzsh
)。
printf -v int %.0f "$float"
次のことができます。
float=1.23
int=${float%.*}
$float
ただし、これは最も近い整数を提供する代わりに小数部を削除するか、1.2e9
exampleなどの.12
値では機能しません。
また、浮動小数点数の内部表現によって発生する可能性がある制限に注意してください。
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
整数を得ることができますが、その整数はどこでも使用できない可能性があります。
また、@BinaryZebraが指摘したように、いくつかのprintf
実装(bash、ksh93、yash、zsh、dash、または以前のバージョンのGNUを除くprintf
)では、ロケールの影響を受けます(小数点区切りは.
、,
または可能性があります٫
)。
したがって、浮動小数点が常にピリオドを小数点区切り文字として使用して表示され、スクリプトを呼び出すユーザーのロケールに関係なく、浮動小数点がそのように処理されるようにするには、printf
ロケールをCに変更する必要があります。
LC_ALL=C printf '%.0f' "$float"
を使用すると、yash
次の操作も実行できます。
printf '%.0f' "$(($float))"
(下記参照)。
POSIX
printf "%.0f\n" 1.1
%f
POSIXはサポートを必要としないため、POSIXではありません。
POSIXlyでは、次のことができます。
f2i() {
LC_ALL=C awk -- '
BEGIN {
for (i = 1; i < ARGC; i++)
printf "%.0f\n", ARGV[i]
}' "$@"
}
awk
言語構文のリテラル数は常に.
小数点文字(,
引数を区切るために使用されるため、数値には使用できません)として使用されますが、ARGV
一部の実装では、ここで示すように入力から数字を取得するときにロケール設定を尊重します。 GNUの場合、これはawk
環境内でのみ適用されます。$POSIXLY_CORRECT
扱いにくい
(浮動小数点算術サポート(小数点区切り記号は常にピリオドです))では、最も近い整数を浮動小数点として提供し(のように)、浮動小数点で整数を提供する数学関数をzsh
使用できます(middleのように)。だからあなたはこれを行うことができます: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
クッシュ 93
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
etcの数学関数はサポートしませんrint()
。以下を使用して数値を整数に変換できます。バイナリまたは例:演算子(これも機能しますzsh
が、適用されませんksh93
)。しかし、小数部は切り捨てられますが、最も近い整数は提供しません。
$ echo "$(( 0.237e2 | 0 ))"
23
$ echo "$(( 1e19 | 0 ))"
-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
答え2
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
答え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
答え4
関連:
補完的なおめでとうございます 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] )}' "$@";
}