質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

9回答

6916閲覧

算術演算子を使わずに乗算する方法

kazu-.

総合スコア34

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2018/11/03 10:23

演算子を使わない方法が思いつかない

どういう考えで算術演算子を使わずに乗算すればいいかわかりません。
考えたのですが、全然思いつきませんアドバイスでいいので助けてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mather

2018/11/03 13:48

なぜ「算術演算子を使わずに乗算」する必要があるのですか?学校の課題などでしょうか?
dice142

2018/11/03 17:56

過去の質問から察するに学校の課題ですよね?何かしら参考資料が提示されてるのではないですか?
guest

回答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

YOshim

総合スコア1085

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

インクリメントとデクリメントだけで四則演算を全て実装してみました。算術演算子禁止として、Arithmetic operators - cppreference.comにある全ての演算子を使用しないようにしました。また、whileforおよび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
raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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
moonphase

総合スコア6621

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukkuri

2018/11/04 15:11

この質問はCについてなので、オブジェクト指向のJavaは違う気がしますがどうなんでしょう。
moonphase

2018/11/04 16:16

はい、ご指摘の通りでした・・・Cでの回答を追記しておきました。
guest

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
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2018/11/03 11:15

リンク先に書いてありますね。 bitだったら、 and すれば、繰り上がりが分かるって。 Xor かと思ったが、大差無い? 複数bitはもう一ひねり必要か。
guest

0

「乗算器」とかで検索したらどうか?

投稿2018/11/05 02:15

fana

総合スコア11634

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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

shsh_

総合スコア113

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YOshim

2018/11/04 02:30

そうそう! 私がやりたかったのは正にこれです。 やはり再帰は素晴らしいですね。
guest

0

シフト演算すれば
i*2 = i<<1
という感じで乗算できますよ。

投稿2018/11/03 10:28

kaisen

総合スコア28

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

shsh_さんが再帰を使った方法を載せてますが、再帰を使わない場合は次のようになります。(addの部分だけ)

C

1int add(int a, int b) 2{ 3 while (b != 0) 4 { 5 int c = (a & b) << 1; 6 a ^= b; 7 b = c; 8 } 9 return a; 10}

投稿2018/11/06 09:18

PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

具体的なコードはしめしませんが、つぎのような方針は如何でしょう?

  1. 九九の表(一桁の数同士の乗算)と 一桁同士の足し算の表を用意する。
  2. 筆算と同様の方法で 上の2つの表を引きながら計算をしていく。

筆算は普通は 10 進でおこないますが、2進数で筆算処理をするなら、小さな表を用意するだけで済ますことができます。
(2進数 <-> 10進の表記変換にいろいろ演算が必要になりますが,それもこの方法で対処できるでしょう)

投稿2018/11/03 14:15

編集2018/11/03 22:56
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問