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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

6回答

1218閲覧

n / a / b = n / (a * b)は常に真でしょうか?

manman

総合スコア233

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

1グッド

0クリップ

投稿2015/12/13 11:41

編集2015/12/13 12:00

これまで何となく使ってきたのですが、
n / a / b = n / (a * b)は常に真でしょうか?

試しに以下を実行したが反例がないので、やはり常に真な気がするのですが
どうでしょうか?

ruby

1(1..501).each{|n| 2 (1..n).each{|a| 3 (1..n).each{|b| 4 p [a, b] if !((n / a / b) == (n / (a * b))) 5 } 6 } 7}
ikuwow👍を押しています

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

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

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

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

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

argius

2015/12/13 11:56

KiyoshiMotokiさんのおっしゃるとおり、プログラミング言語によると思いますが、もしRubyに限った質問であれば、タグにRubyをつけたほうが良いと思います。
manman

2015/12/13 12:29 編集

タグを「プログラミング言語」から「Ruby」に変更しました。
guest

回答6

0

ベストアンサー

Rubyで整数の範囲では、真でしょう。
Rubyの整数は無限精度なので。

浮動小数点の場合は、有限精度なので真とは限らない。
偽となる例を1つ挙げておきます。

Ruby

1puts 2.0/0.1/7.0==2.0/(0.1*7.0) #=> false

投稿2015/12/13 12:18

編集2015/12/13 12:23
otn

総合スコア84533

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

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

manman

2015/12/13 12:39

盲点を突かれました。
guest

0

プログラミング言語タブなので、C/C++の場合で回答してみます。

CやC++言語のように整数型演算のオーバーフローを無視するような言語ですと、常に真にはなりません。
今は少ないですが、整数型(int)が-32768~32767の範囲しか表現できない処理系だった場合、
信じがたいと思いますが(32767*2)=-2となってしまう処理系が多く、10/(32767*2)=-5となるものがあります。10/32767/2=0なので結果が異なります。
今でもint型だけの演算で、int型の上限を超える計算をさせると同じような問題が起きます。


【追記】
げっ、タブがRubyに変わっちゃいました。私が回答した時はプログラミング言語だったので許してください。

投稿2015/12/13 12:17

編集2015/12/13 12:23
Chironian

総合スコア23272

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

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

0

言語仕様によるのではないでしょうか?

以下のリンクの"プログラミング言語"という項によると、

多くのプログラミング言語では、算術におけるそれと同じ優先順位である。しかし、中にはAPLやSmalltalkのように演算子の優先順位を持たない言語もある(APLではなんでも右から左へと評価していく。Smalltalkでは、なんでも左から右へと評価していく)。

https://ja.wikipedia.org/wiki/%E6%BC%94%E7%AE%97%E5%AD%90%E3%81%AE%E5%84%AA%E5%85%88%E9%A0%86%E4%BD%8D

とありますので、少なくともAPLという言語では異なる結果になりそうです。

あとは、aまたはbnに比べて非常に大きい値にした場合も、誤差が発生するかもしれません。

投稿2015/12/13 11:50

編集2015/12/13 11:54
KiyoshiMotoki

総合スコア4791

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

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

0

コンピュータでの計算では,桁数が有限だということに注意する必要があります。

極端な例として int を 2 bit で表している 言語で考えてみます。

この言語では 2/2/2 は 0 になります。
2/(22) は 22 の計算時にこの言語であらわせる整数の範囲を超えてしまいます。
言語によっては此処でエラーが発生して値は得られないことになります。
エラーが発生せず単に下の桁だけを取り出すようになっている場合は 2*2 は 0 となるかもしれません。
そして、計算を続けようとすると 2/0 となり、今度は 0 での割り算でのエラーとなるでしょう。

つまり、数学上では n / a / b = n / (a * b) ですが、
コンピュータでの計算では これが成り立たない例があるのです。

桁が有限な事の影響は掛け算だけで起こるわけではありません。
n == m と (n + 1) == (m + 1) は、判定結果が異なるケースもあります。
n + 1 の計算時に桁があふれたら、言語によってはエラーが発生するからです。

int でなく、double での場合でもいろいろな問題が発生することあります。
2次方程式の解の公式の数式をそのまま計算したのでは、実際の値は大きく異る値になってしまうことがあります。(これは数値計算系の教科書でよく出てくる例です)

投稿2015/12/13 12:27

katoy

総合スコア22324

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

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

0

基本的には真ですが、a * bがオーバーフローを起こした場合は結果が変わります。また、浮動小数点の場合は丸め誤差によって結果が変わる可能性があります。

投稿2015/12/13 12:00

catsforepaw

総合スコア5938

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

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

0

(証明)以下、積は*記号を用いず文字を並べて表現する。
n = pa + q, p = rb + s(ただし、p, q, r, sは0以上の整数で、q < a, s < b)とする。
この時、n / a / b = rである。
n = (rb + s)a + q = rab + (sa + q)

ここでsa + q < abが示せれば、nをabで割った商がr,余りがsa + qということになり、
n / ab = rとなる。

sa + q - ab = a(s - b) + q
s, bは0以上の整数でs < bなのでs - bは-1以下の整数
よってa(s - b) <= -a
a(s - b) + q <= q - a < 0(∵q < a)
よってsa + q < ab
したがってsa + qは、nをabで割った余りに相当する。
つまり、n / ab = r = n / a / b (証明終了)

投稿2015/12/13 11:58

編集2015/12/13 12:03
swordone

総合スコア20651

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

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

swordone

2015/12/13 12:10

見返してみるとn,a,bが正の時しか証明してませんね… 整数全体で証明できるかな…?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問