
スケールがゼロ以外の場合、3%2 や 46%4 などの % を使用した計算では 0 が出力される傾向があります。スケールが 0 以外の場合、アルゴリズムはどのように設計されていますか?
bc
scale=10
print 4%3 // output 0
答え1
のコマンドマニュアルBC がモジュロを計算する方法については、次のように述べられています。
式の結果は「剰余」であり、次のように計算されます。a%bを計算するには、まず1/2 ...は桁数に応じて計算されます。その結果は計算に使用されますa - (a/b) * b (ア)scale+scale(b)とscale(a)の最大値のスケールに。スケールがゼロに設定され、両方の式が整数の場合、この式は整数剰余関数になります。
編集: GNU BC のソース コードを確認したところ、mod 演算子が除算演算子を拡張していることがわかりました。つまり、剰余は除算の副産物として計算されます。剰余を計算するには整数除算を使用します。
scale
ただし、 が設定されている場合は、整数除算は行われません。
BC でこれを試してください:
bc
scale = 0
print 5/2
scale = 5
print 5/2
次のような結果になるはずです:
2 << Integer Division
2.50000 << NOT integer division!
さて、これらの数字をBCと同じように入力してみましょう。マニュアルには次のように書かれています。a-(a/b)*b計算します。整数除算の結果とscale
0 以外の値の 2 つの結果を代入してみましょう。
a - ( a/b ) * b
5 - ( 2 ) * 2 = 1 << CORRECT!
5 - ( 2.5 ) * 2 = 0 << VERY WRONG!
整数除算なし:
a - ( a/b ) * b == a - ( a ) == 0
このため、モジュロが正しく機能するにはスケールを0に設定する必要があります。
この問題は、BCの設計と、それが「スケール」を持つ数値をどのように処理するかから生じているようです。モジュロが正しく機能するためには整数除算が必要です。
がある他の多くのより高度なツールこれらはこの目的のために無料でオープンソースで提供されていますので、使用することをお勧めします。
答え2
user272970 さんの回答は素晴らしいです。ここに少し手を加えます:
define int(x) { auto oldscale; oldscale=scale; scale=0; x=x/1; scale=oldscale; return( x ); }
define fmod(x,y) { auto oldscale; oldscale=scale; scale=1000; x = x - y * int(x/y); scale=oldscale; return( x ); }
これにより ( を使用auto oldscale
)、 はoldscale
関数に対してローカルになります。これがないと、fmod() から を設定すると、 に保存しようとしている が上書きされoldscale
、を呼び出す前の値ではなく 1000 に設定されます。int()
oldscale
fmod()
scale
fmod()
これらの関数を に追加し~/.bcrc
、BC_ENV_ARGS
環境変数を に設定しました。これにより、bc を実行するたびにこれらの関数がロードされます。そのため、毎回これらの関数を手動で定義しなくても、bc にいるときはいつでも~/.bcrc
実行できるようになりました。fmod(x,y)
1000psscale
はほとんどの場合やりすぎかもしれない
答え3
私は次のように解決しました:
整数
int(x) を定義します { oldscale=scale; scale=0; x=x/1; scale=oldscale; return( x ); }
モジュロ
mod(x,y) を定義します { oldscale=scale; scale=1000; x = x - y * int(x/y); scale=oldscale; return( x ); }
HTH
答え4
a%b
他の回答者が述べているように、これはを として定義し(a-(a/b)*b)
、現在の で評価した結果ですscale
。つまり、これを整数係数として機能させたい場合は、 で使用する必要がありますscale=0
。
しかし、私はそれが「間違っている」という意見には同意しません。これは、特にエラーを評価する場合に潜在的に有用なツールです。
scale=5
1/3
> .33333
1%3
> .00001
7/13
4桁の小数で表すと何が失われるのでしょうか.5384
?
scale=4
7/13
> .5384
7%13
> .0008
どうやら0.0008/13
。
そして最後に、整数の使用を要求しないため、小数の一部を抽出するのに使用できます。
scale=1
123.456/1
> 123.4
123.456%1
> .056