[ruby-list:50951] Re: 整数同士の乗数を求めるとComplexになるのはなぜでしょうか

From: "wanzerbusi@..." <wanzerbusi@...>
Date: 2022-05-21 14:50:23 UTC
List: ruby-list #50951
プログラムはこれですね。
#!/usr/bin/env ruby

def isPrime2(i)
  # 1は素数ではない
  return false if i == 0 || i == 1

  # 2は素数
  return true if i == 2

  judge = true
  (2..i).each do |j|
      # root i までで十分
      break if j > i**0.5
      if i % j == 0
            judge = false
            break
      end
   end
   judge
end

def chkPrime(prm)
  if isPrime2(prm)
    puts "#{prm}は素数"
  else
    puts "#{prm} is not prime number"
  end
end

def mkPrime(prm)
  prime_array = []
  first_prime = 2
  previous_prime = first_prime - 1
  last_prime = first_prime + previous_prime
  prm.to_i.times do |i|
   current_prime = previous_prime ** last_prime + previous_prime + 1
   chkPrime(current_prime) if current_prime.to_i.positive? 
   previous_prime -= current_prime
   last_prime = current_prime
  end
end

prm = ARGV[0].nil? ? 100 : ARGV[0].to_i
mkPrime(prm)

で、この長さならできれば添付でなくソース貼っても良いかと思います。(昨今は携帯といったように添付ファイルが見れない環境もありうるため)

それと、素数といえばエラトステネスの篩を使うのが真っ先に思いつきます。
思想上使いたくないなら構いませんが、調べればQiitaがすぐ引っかかりました・・・
例
https://qiita.com/shizuma/items/a8b5e2b22708b43216d4

さとうしんじ

----- Original Message -----

From: "大城 尚紀" <n-oshiro@tec.u-ryukyu.ac.jp>
To: "Ruby users (Japanese)" <ruby-list@ruby-lang.org>
Date: 2022/05/21 土 22:18
Subject: [ruby-list:50950] Re:	整数同士の乗数を求めるとComplexになるのはなぜでしょうか


下田さん、こんにちは。大城と申します。

(昨日送信したのですが、メールアドレス違いで投稿できていなかったようです。Sekiさんからも同様のご指摘きていますが、再送致します。)

ちょっと見てみました。途中で出てくるRationalの値が次の段階で「負数の小数乗」になって、複素数となるようです。ですので、整数同士の乗数の演算ではありません。

first=2, prev=1, last=3から始めて、cur=prev**last+prev+1=1**3+1+1=1+1+1で3。更新して、prev-=cur, last=curで、prev=-2, last=3となって、この段階でcur=-9になります。curが負数なので判定はなしですが、更新して、prev-=curで7, last=-9になります。

このprev=7; last=-9 の状況で、curを求めると cur=prev**last+prev+1=7**(-9)+7+1ですが、始めのマイナス乗の段階で逆数になって7**(-9)で1/40353607のRationalになります(微小値)。さらに(+7+1)の8となる加算をして322828857/40353607 となり、これが表示されています。

この 322828857/40353607は、実数にして小数点以下を求めてみると8.00000002478093となります。この段階で整数でなくなっています(また、ざっくり8だったとしても素数でもないので、算出式か判定が誤っているかもしれません)。

それで、次の更新で、prev -= cur で -1.00…2478…(負数)、last=curで8.000…2478…(小数点以下の情報あり)になって、prev**lastの演算を行うと(-1.00…)**8.000…2478で、実質√(-1)のような形になって複素数になるようです。(-1)**(0.000000025)というような状況です。

curを8に近い値(小数点以下が発生する値)として、以下のように80/11としても同様に複素数になります(Rationalであっても、もし80/10であれば更新値は1/1として複素数にならずに求まります)。

 prev = 7; last = -9; cur = Rational(80, 11)
 prev -= cur; last = cur
 print("#{prev} #{last} #{prev**last}\n") # -3/11 80/11 -5.156520268369788e-05-5.950941621574082e-05i

上記のcurの設定箇所をRational(80,11).to_fとして、実数にしても同様に複素数になります。



> ----- Original Message -----
> 
> From: "Masao Seki" <ma-seki@gb3.so-net.ne.jp>
> To: "ruby-list@ruby-lang.org" <ruby-list@ruby-lang.org>
> Date: 2022/05/21 土 22:15
> Subject: [ruby-list:50949] Fwd:  Re: 整数同士の乗数を求めるとComplexになるのはなぜでしょうか
> 
> 
> 下田さん、
> 
> 取敢えず、一段落したようで良かったです。
> でも、一言老婆心ながら申し添えると、数論の初心者が計算実験するツール
> としてrubyを使うのは、私はあまりお奨めしません。
> rubyは、間違いなく、様々な用途で威力を発揮する素晴らしい言語ですが、
> 動的に型が変化する、私のようなfortran/C++/Javaで育った人間には、
> 少し柔軟過ぎるのではとさえ、思える言語です。(最後にrubyのツールを
> 作ったのが、10年位まえのruby-2.2での事なので、今のrubyには当たらない
> 可能性、大です。)
> 数論の計算実験をするには、多倍長演算が必須になりますが、多倍長演算の
> 基本を理解した上で、明示的に多倍長演算をサポートしてくれるライブラリ
> (言語)を活用される事をお奨めします。
> 
> 本題から外れますが、mailing-list(ML)への返信は、個人宛てではなく、
> ML宛てでお願いします。(大抵のmailing toolでは、返信時、差出人宛か、
> ML宛か選択できると思います。)私のみに返信して頂いても、MLを受信して
> いる他の方には、状況の推移が伝わりませんので、尻切れトンボ状態になっ
> てしまいます。個人的な内容を含んでいて、MLに出したくない場合は、その
> 旨明記した上で、個人宛てに返信下さるのは、構いません。
> 今回は、そのようなケースでないと判断しましたので、全文引用の上、MLに
> 返信します。
> 
> 
> -------- Forwarded Message --------
> Subject: Re: [ruby-list:50948] Re: 整数同士の乗数を求めるとComplexになる 
> のはなぜでしょうか
> Date: Sat, 21 May 2022 21:01:22 +0900
> From: Jun'ya Shimoda <junshimo2@gmail.com>
> To: Masao Seki <ma-seki@gb3.so-net.ne.jp>
> 
> Seki様
> すみません、ありがとうございます。
> 
> そもそも素数に興味があって調べてたんですけど
> 2の次の素数乗+1
> 辺りでおかしなことになるということが
> 大体分かったんでヨシとします。
> 
> Rubyの言語の問題じゃなくて
> 数学的な話だったんですよ。
> 私の数学の愛読書によると
> 素数を求める公式もまだ出来てなくて
> 私の予想では2の次の素数乗+1
> つまり2**2+1 == 5
> の計算をしたところで
> 何らかの不具合が発生してるらしいと思ってます。
> 整数同士の累乗の計算なのに
> Complexに変換されるのも
> 多分5の累乗か何かの理由なんじゃないかと思います。
> 
> Rubyの実用上はほとんど問題ないのですが
> Rubyのnextでも落ちることがあるのですが
> 多分そんなような理由なんだと思います。
> ruby-langに投稿できるほど分かってないので
> 自粛します。
> 
> まつもとさんのQuoraで
> 「暇ならCommonLispやれ」って言ってたんで
> それも興味あるんですよね。
> 細かい式を忘れたんですが
> Rubyの計算結果と
> Lispの計算結果が違うところがあって
> Facebookの数学の先生やってる人に
> 聞いたりしてました。
> 多分Rubyの計算結果の方が正しいんだと思いますよ。
> 雑談になっちゃてすみません。
> 
> ありがとうございました。
> 
> On 2022/05/21 20:35, Masao Seki wrote:
> > もしかして、322828857/40353607が整数と思い込んでいて、
> > 解決に近付けないでいたりしていませんか?
> >
> > 322828857/40353607 = 8.00000002478…
> > 322828857: 3^2 13 229 12049
> > 40353607: 7^9
> 





2022年5月20日(金) 17:04 Jun'ya Shimoda <junshimo2@gmail.com>:
下田と申します。
 今、確実に素数を求めるプログラムを作ろうと頑張ってます。
 添付ファイルがプログラムです。
 
 ruby ./mk_prime.rb
 で実行すると
 「3は素数
 322828857/40353607は素数
 ./mk_prime.rb:37:in `to_i': can't convert 
 1.00000017346654+7.785160984669524e-08i into Integer (RangeError)]」
 
 というエラーになるんです。
 整数しか扱ってないプログラムなのに
 Complexになる理由が分かりません。
 
 よろしくお願いします。
 

In This Thread

Prev Next