演算子を使わない方法が思いつかない
どういう考えで算術演算子を使わずに乗算すればいいかわかりません。
考えたのですが、全然思いつきませんアドバイスでいいので助けてください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/11/03 17:56

回答9件
0
算術演算を論理演算で代用したいという目的であるという前提で検討しました。
考え方を以下に示します。
まず掛け算の前に2つの整数の和を、論理演算子で記述する方法を考えます。
①2つの整数の排他的論理和を取ります。これは繰り上がりがない場合の足し算の結果に等しいです。
②2つの整数の論理積を取ります。bitが1となっている桁は繰り上がりが発生する桁を意味します。
③上記の②の結果を1bitシフトしたものと①の結果について、再び排他的論理和と論理積を取ります。
④上記の③を排他的論理和または論理積が0になるまで繰り返します。これは繰り上がりがなくなることを意味します。
⑤最終的に算出された排他的論理和と論理積の論理和(一方は0なので排他的論理和でもよい)が2数の和になります。
掛け算の場合は、2数が同じ数値という前提で、繰り返す回数を指定すればよいです。
2数の和の計算を論理演算子のみで実現するコードは以下です。
int bitSum(int numA, int numB){ int result; int bitAND; int bitANDOld; int bitEXOR; int bitEXOROld; bitANDOld = numA; bitEXOROld = numB; while(bitEXOROld !=0 && bitANDOld !=0){ bitAND = (bitANDOld & bitEXOROld) << 1; bitEXOR = bitANDOld ^ bitEXOROld; bitANDOld = bitAND; bitEXOROld = bitEXOR; } result = bitANDOld | bitEXOROld; return result; }
掛け算の場合は以下のコードで実現できます。
*for文中の++はご容赦ください。
int bitProduct(int num, int multiple){ int result = num; int bitAND; int bitANDOld; int bitEXOR; int bitEXOROld; for(int i = 0; i<multiple -1;i++){ bitANDOld = num; bitEXOROld = result; while(bitEXOROld !=0 && bitANDOld !=0){ bitAND = (bitANDOld & bitEXOROld) << 1; bitEXOR = bitANDOld ^ bitEXOROld; bitANDOld = bitAND; bitEXOROld = bitEXOR; } result = bitANDOld | bitEXOROld; } return result; }
投稿2018/11/03 14:15
総合スコア1094
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
インクリメントとデクリメントだけで四則演算を全て実装してみました。算術演算子禁止として、Arithmetic operators - cppreference.comにある全ての演算子を使用しないようにしました。また、while
やfor
およびgoto
を用いたループも禁止しました。
C
1/** 2 * Implementation of arithmetic operators without using arithmetic operators. 3 * https://en.cppreference.com/w/c/language/operator_arithmetic 4 */ 5 6#define NDEBUG 7#include <assert.h> 8#include <stdio.h> 9 10int plu(int a); // +a 11int min(int a); // -a 12int add(int a, int b); // a + b 13int sub(int a, int b); // a - b 14int pro(int a, int b); // a * b 15int div(int a, int b); // a / b 16int mod(int a, int b); // a % b 17 18int plu(int a) { return a; } 19 20static inline int min_inc_r(int a, int b) 21{ 22 if (a == 0) return b; 23 assert(a < 0); 24 return min_inc_r(++a, ++b); 25} 26 27static inline int min_dec_r(int a, int b) 28{ 29 if (a == 0) return b; 30 assert(a > 0); 31 return min_dec_r(--a, --b); 32} 33 34int min(int a) 35{ 36 if (a == 0) return 0; 37 if (a < 0) return min_inc_r(a, 0); 38 return min_dec_r(a, 0); 39} 40 41static inline int add_r(int a, int b) 42{ 43 if (b == 0) return a; 44 assert(b > 0); 45 return add_r(++a, --b); 46} 47 48int add(int a, int b) 49{ 50 if (b < 0) return min(add(min(a), min(b))); 51 return add_r(a, b); 52} 53 54int sub(int a, int b) { return add(a, min(b)); } 55 56static inline int pro_r(int a, int b, int r) 57{ 58 if (b == 0) return r; 59 assert(b > 0); 60 return pro_r(a, --b, add(r, a)); 61} 62 63int pro(int a, int b) 64{ 65 if (b == 0) return 0; 66 if (b < 0) return pro(min(a), min(b)); 67 return pro_r(a, b, 0); 68} 69 70static inline int div_r(int a, int b, int r) 71{ 72 assert(b > 0); 73 if (a == 0) return r; 74 if (a < 0) return --r; 75 return div_r(sub(a, b), b, ++r); 76} 77 78int div(int a, int b) 79{ 80 if (b == 0) return 0; // or error 81 if (b < 0) return min(div(a, min(b))); 82 if (a < 0) return min(div(min(a), b)); 83 return div_r(a, b, 0); 84} 85 86int mod(int a, int b) { return sub(a, pro(div(a, b), b)); } 87 88int main(void) 89{ 90 printf("+42 = %d\n", plu(42)); 91 printf("-42 = %d\n", min(42)); 92 printf("7 + 6 = %d\n", add(7, 6)); 93 printf("7 - 6 = %d\n", sub(7, 6)); 94 printf("7 * 6 = %d\n", pro(7, 6)); 95 printf("7 / 6 = %d\n", div(7, 6)); 96 printf("7 %% 6 = %d\n", mod(7, 6)); 97}
div()
は、0除算でエラーにならない事を除き、標準の/
と動作を合わせたつもりです、たぶん。**速度は全く考慮に入れていません。**インクリメントのオーバーフローやデクリメントのアンダーフローは考慮していませんが、末尾再帰になっていますので、適当に最適化オプションを付けていればスタックオーバーフローは起きないはずです。assert()
を有効にしたい場合は#define NDEBUG
をコメントアウトしてください。ビット演算子やシフト演算子の実装については力尽きましたので、誰かがやってくれることでしょう。
投稿2018/11/03 13:25
編集2018/11/04 02:41総合スコア21741
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
論理演算子は既に出ているので別の方法で。
本来何を解決したいかわからないので検討違いならすみません。
Java
1BigDecimal two = new BigDecimal("2.00"); 2BigDecimal three = new BigDecimal("3.00"); 3 4BigDecimal multiply = two.multiply(three); 5System.out.println("結果: " + multiply);
以下追記
C言語でしたね、見落としていましたすみません。
GMPという多倍長計算を非常に高速に行うライブラリがあるのでそれを使いました。
#include <stdio.h> #include "gmp.h" int main(int argc, char **argv) { mpz_t a, b, x; mpz_init(x); mpz_init_set_str(a, "2", 10); mpz_init_set_str(b, "3", 10); mpz_mul(x, a, b); mpz_out_str(stdout, 10, x); mpz_clear(a); mpz_clear(b); mpz_clear(x); }
投稿2018/11/03 12:08
編集2018/11/04 16:16総合スコア6621
0
論理演算とシフトである程度出来ます。・・・全部は思いつかない;;
a=(1|(1<<2))→5とか・・・
5×3だと・・(5<<1)+5なんだが・・・“+”をどうするか??
・・・例が悪かった^^; 1010|101→1111→15・・出来ちゃたw
ビットが重ならなければor('|')でなんとかなるが・・・8×3は・・(8<<1)|8で出来る
投稿2018/11/03 10:47
編集2018/11/03 11:20総合スコア6851
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/11/03 11:15

0
とりあえずコードだけ。
C
1#include <stdio.h> 2 3int add(int n, int m) 4{ 5 if (n & m){ 6 return add(n ^ m, (n & m) << 1); 7 } 8 9 return n | m; 10} 11 12int mul(int n, int m) 13{ 14 int result = 0; 15 16 for ( ; n && m; n >>= 1, m <<= 1){ 17 if (n & 1){ 18 result = add(result, m); 19 } 20 } 21 22 return result; 23} 24 25int main() 26{ 27 int n = -100; 28 int m = -10; 29 30 printf("%d * %d = %d\n", n, m, mul(n, m)); 31 32 return 0; 33} 34
投稿2018/11/04 02:01
総合スコア113
0
具体的なコードはしめしませんが、つぎのような方針は如何でしょう?
- 九九の表(一桁の数同士の乗算)と 一桁同士の足し算の表を用意する。
- 筆算と同様の方法で 上の2つの表を引きながら計算をしていく。
筆算は普通は 10 進でおこないますが、2進数で筆算処理をするなら、小さな表を用意するだけで済ますことができます。
(2進数 <-> 10進の表記変換にいろいろ演算が必要になりますが,それもこの方法で対処できるでしょう)
投稿2018/11/03 14:15
編集2018/11/03 22:56総合スコア22328
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。