これが私のロシア農民乗算の簡単な実装です。どうすれば改善できますか?
制限事項: a>0,b>0 の場合のみ機能します
for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);
空白、適切なインデント、および適切な関数本体を追加することで改善できます。
int peasant_mult (int a, int b) {
for (p = 0;
p += (a & 1) * b, a != 1;
a /= 2, b *= 2);
return p;}
見る?for
これで、宣言の 3 つの部分がどのように使用されるかが明確になりました。プログラムは主に人間の目のために書かれていることを忘れないでください。読めないコードは常に悪いコードです。
そして今、私の個人的な娯楽として、末尾再帰バージョンがあります:
(defun peasant-mult (ab &optional (sum 0)) "a と b の積を返します。 農民の乗算によって達成されます。」 (もし (= 1) (+ b 合計) (農民マルチ(床(/ A 2)) (※b2) (+ 合計 (* b (対数 a 1))))))
ひどいと思いますこれはコンパイラの観点からはまったく同じコードであり、(願わくは)より明確です
int sum = 0;
while(1)
{
sum += (a & 1) * b;
if(a == 1)
break;
a = a / 2;
b = b * 2;
}
そして今、私はそれを書きました、私はそれを理解しています。
これを改善するための本当に簡単な方法があります:
p = a * b;
a または b が 0 未満になる可能性があるという利点さえあります。
それが実際にどのように機能するかを見ると、それがバイナリで実行される通常の手動乗算であることがわかります。あなたのコンピューターは内部でこのように処理するので (1)、ロシアの農民法を使用する最も簡単な方法は、組み込みの乗算を使用することです。
(1) より洗練されたアルゴリズムを持っているかもしれませんが、原則として、このアルゴリズムで動作すると言えます。
ループにはまだ乗算があります。乗算のコストを削減したい場合は、代わりにこれを使用できます。
for(p=0;p+=(-(a&1))&b,a!=1;a>>=1,b<<=1);
他の人が言うように、私はそれが特にひどい、難読化されている、または読めないとは思いませんし、それらすべての反対票を理解していません. これは言った、これが私がそれを「改善」する方法です:
// Russian Peasant Multiplication ( p <- a*b, only works when a>0, b>0 )
// See http://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication
for( p=0; p+=(a&1)*b, a!=1; a>>=1,b<<=1 );
p
初期化されていません。
a
がゼロの場合はどうなりますか?
a
が負の場合はどうなりますか?
更新:上記の問題に対処するために質問を更新したようです。コードは記述どおりに動作しているように見えますが (オーバーフローの問題を除いて)、本来よりも読みにくくなっています。
これはコードの難読化コンテストのためですか? 私はあなたがもっとうまくやれると思います。まず、意味のない変数名ではなく、誤解を招くような変数名を使用してください。
不完全で読みにくいと思います。どのような具体的なフィードバックを求めていましたか?
int RussianPeasant(int a, int b)
{
// sum = a * b
int sum = 0;
while (a != 0)
{
if ((a & 1) != 0)
sum += b;
b <<= 1;
a >>= 1;
}
return sum;
}
掛け算も割り算もなしで答えてください。
function RPM(int a, int b){
int rtn;
for(rtn=0;rtn+=(a&1)*b,a!=1;a>>=1,b<<=1);
return rtn;
}