• 締切済み

pythonで桁の大きな数字を調べる方法

pythonですが、簡単なプログラムで計算しても10000!とかが計算できてしまいます。コンピュータで使える数字の桁数って限定されると思っていたのですが、pythonだと計算できるのでしょうか。 なお、ちゃんと計算できているのかどうか不明ではありますが。 また、ものすごく桁数が長い数字とか無理数とかですが、数字(0-9)が表れる頻度を調べることができないかと思いますが、プログラムを組むことは可能でしょうか。円周率でも平方根、ネイピア数とかでもですが。かなりイーブンになるものでしょうか。10000!とかだと原理的に0が多くなるようですが。 よろしくお願いします。

  • Python
  • 回答数3
  • ありがとう数2

みんなの回答

  • hue2011
  • ベストアンサー率38% (2800/7250)
回答No.3

これはおそらく目の付け方に間違いがあります。 確かにIntegerとかFloatとか、そういう型は存在しますが、pythonではvariantなんです。variantというのは適宜変換するということです。 a=20 b= a+14 なんてやっていたら、aは当初intとしてアサインされます。 ところが a = a*100*100*100*100 なんてやったらfloatに勝手に変換されます。 オーバーフローは発生しません。しかも仮想小数点ですから、2e13なんていう形で扱うことができ、大概の数字が扱えることになります。 しかし、ご存知だと思うんですが、フローティングの数字にすると「桁落ち」がおきます。 2e15+1 なんていう計算は2e15になってしまうのです。全体のうちのわずかな分量は無視されます。 ここは金額計算なんかをするときに気を付けなければいけないので、末尾まで確実な計算をしたいのであれば x= int(a)+ int(b) というように、整数形式にして演算する必要があります。 もし円ではなく銭単位にしたいのだったら100倍して計算し、表示するときに100で割ってフローティングにし、fタイプのフォーマットで出力すればいいのです。 このヴァリアントのなかで苦情を言われるのは文字型の数字です。 たとえばファイルに"123”という文字が書いてあって、それを読んでprintすると '123' と表示されます。これがmという変数に入れられたとしたとき、 print (m*100) は可能です。その場合 12300 という表示になります。 print (m) のときの123は文字列なんです。print (m*100)の結果は数値なんです。 これをあまり意識しないでプログラムすると、途中でエラーが発生します。 だから文字列として扱いたいときはstr(m)と書くのです。数字として扱いたいなら int(m)とするんです。 この話は、比較するときに意識しろということです。 mがintでnがstrなら==で比較するのは意味がありません。 どうしても比較するときには同じ形である必要があるんです。

回答No.2

> pythonはFortran, Cなどの伝統的なプログラム言語とどこか一線を画するようなところがあるのでしょうか。 んー、伝統的かどうか、と言うより「ハードウェアに密接に関係している」か否か、って事でしょうね。Cはノイマン型計算機、要するに今主流のコンピュータですね、での「低レベルで効率的なプログラムを作成する為」設計されていて、効率重視、と言う意味ではFortranもそんなに変わらないでしょう。 Pythonは逆に「プログラミングしやすさ」「ロジック自体を(工学的理由に依らず)追求出来る」ように設計されています。ただ、これも方向性としては「伝統的」で昔からある考え方です。ただ、(Fortranがブイブイ言わせていた)当時と今と何が決定的に違うのか、と言うとハードウェアの処理速度がメチャクチャ速くなった、って事ですね。 Pythonのようなプログラミング言語は「実験室」の中には存在していましたが、市井のマシンは研究室で扱うような「大型コンピュータ」ではないので、それに比べると昔は低速でした。従ってPythonのようなプログラミング言語は「非効率的で非実用的」だった、と言う事です。ところが今はハードウェアが当時の大型コンピュータを凌駕するようなスピードを獲得してるので、「昔は非効率的と思われた」アイディアが、現在だと実用レベルになった、ってそれだけの話ですね。 注: 例えば、Javaは「JVM(Java仮想マシン」上で走るコードを生成するコンパイラ言語で、これがWrite once, Run anywhere(一度(プログラムを)書けば、どこでも実行できる)の理由になっていて、プラットフォーム毎に仮想マシンを用意しておけばどのマシンでもプログラム実行に問題がない環境を実現してる。 が、このアイディア自体は既にそれより20年程前のPascalで実現してて、実際元々Pascalは仮想マシン対象にコンパイルするプログラミング言語だった。つまり「仮想マシン」は別にJavaが「初めて」実現した方法ではない。しかしながら、大型コンピュータ用に元々作られたPascalを「仮想マシン」込みで民生機に持ってくるのはこれがなかなか「資源の無駄遣い」で、8bitパソコン黎明期を除き、仮想マシン対象のPascalは16ビット機以降殆ど使われなくなる(つまり直接機械語/アセンブリ言語に翻訳する処理系が中心となった)。 このように「アイディアが良くても」機械の処理速度が遅いと、民生機上で「実用的に使える」まで時間がかかる、と言うのは良くある事である。 例えば、「超」高級言語としてLispと言うプログラミング言語があります。例えばそのうち、Schemeと言う方言は1975年登場で、と言う事はC言語とほぼ登場時期が同じなんですが(C言語は1972年登場)、こいつも10000!なんかヘーキで計算しますね。 (define (factorial n)  (let loop ((n n) (acc 1))   (if (zero? n)     acc     (loop (- n 1) (* n acc))))) (factorial 10000) 結果は桁数がものすごく多くなるんで、ここには載せませんが(笑)、こいつもPythonと同じように「ハードウェア資源が許す限り」どんな大きな数になってもヘーキで計算します。 (例えば https://download.racket-lang.org/ から処理系を入手してみて実験してみて下さい) これは要するにSchemeの言語仕様で「どんな大きな数になろうと正確な値を返せ」と要求しているから、です(そしてそれを実現する為のプログラミングはメチャクチャ大変ですね・笑。脱帽します)。 そして、伝統的かどうか、と言うより「PythonはCよりLispに近い」発想で設計されている、と言う事です。 > 無理数における数字出現率の傾向を調べるのはこれらの古典的言語でも簡単でしょうか。 任意の無理数さえ獲得すればそんなに難しくないでしょう。あとは、C言語やFortanで扱える「最大の整数」が何か、と言うのさえ把握していれば良いですよね。 つまり、プログラミングは言語によっては「ロジック」ともう一つ「工学上の理由」が要求される場合があって、C言語はその「後者」をケアしないといけない。一方、PythonやLispは後者を「考えなくて良い」ってのが違いで、とは言っても「ロジック」自体は要するに同じですよね。 例えば、前に見せたプログラム >>> import math >>> summary = {str(i):0 for i in range(10)} >>> for key in str(math.factorial(10000)):    if key in summary:     summary[key] += 1 >>> summary {'0': 5803, '1': 3241, '2': 3416, '3': 3258, '4': 3341, '5': 3324, '6': 3324, '7': 3335, '8': 3336, '9': 3282} >>> ってのは 1. カウントした「結果」を格納する為の変数summaryを作る(この場合はラベリングがあるのでPythonの辞書型を利用したが、C言語なんかは「長さが10の」配列を用意すれば良い)。 2. このケースの場合は10000!を計算し、結果を文字列に変換してる(C言語の場合でも文字列に変えられれば"数値を文字化した"「配列」を用意した事になる)。 3. 変換した文字列の頭から一文字一文字、「何の数値なのか」確認していって、変数summaryの対応する場所に+1していく。 つまり、「ロジック」自体はPythonでもLispでもC言語でも同じですね。別に変わらない。 ただ、PythonやLispだと「ロジックをそのまま記述すれば」プログラムは完成しますが、C言語なんかの場合だと 1. long型で10000!をそのまま計算出来るのか?計算「させる」為に何か特殊なプログラミングテクニックが必要にならないか? 2. 変数summaryの各格納庫の上限はint型やlong型で間に合うのか?10000!が何桁になるか分からないので、当然各格納庫の「上限」もどうなるか分からない。 3. 10000!をどうやって「配列化」するにせよ、その「配列」の長さがどうなるのかサッパリ分からない。 と言う問題が出てきますよね。ここはぶっちゃけ「ロジック」は全く関係なくって、「C言語を扱う上での工学上の問題」です。C言語だとこういう「工学的な壁」がアチコチ立ちはだかるので、結果C言語プログラミングはメンド臭くて厄介になるわけですね。 写真: 同じくLisp系言語Common Lispでの10000!の各数字(0~9)の出現率を調べるプログラム。 0が5803個、1が3241個ある、とPythonでの解と一致している。

回答No.1

> コンピュータで使える数字の桁数って限定されると思っていたのですが、pythonだと計算できるのでしょうか。 はい、出来ます。 C言語のような低レベルな言語だと限定されてるんですが、仕組みとしてはメモリのひと塊(8bit、16bit、32bit、64bit等)で扱える数が上限ですが、Python(や同じくC等より高級な言語)の場合、必要になったらもっとメモリの塊を追加出来るように設計してるので、必要な分だけの数が計算出来ます。 ただし、本当の上限は、要するに貴方が持ってるPCがメモリをどの程度搭載してるかに左右されます。が、それを全部使い切るのは貴方が想像してる以上のデカさの数でしょうから、気にしなくて結構です。 > また、ものすごく桁数が長い数字とか無理数とかですが、数字(0-9)が表れる頻度を調べることができないかと思いますが、プログラムを組むことは可能でしょうか。円周率でも平方根、ネイピア数とかでもですが。 出来るんじゃないですか? その「数」の計算方法は任せますが、例としては次のように出来ますね。 >>> import math >>> summary = {str(i):0 for i in range(10)} >>> for key in str(math.factorial(10000)):    if key in summary:     summary[key] += 1 >>> summary {'0': 5803, '1': 3241, '2': 3416, '3': 3258, '4': 3341, '5': 3324, '6': 3324, '7': 3335, '8': 3336, '9': 3282} >>>

skmsk1941093
質問者

お礼

回答ありがとうございました。pythonはFortran, Cなどの伝統的なプログラム言語とどこか一線を画するようなところがあるのでしょうか。無理数における数字出現率の傾向を調べるのはこれらの古典的言語でも簡単でしょうか。こういう分野をやったことがないのでコード化を思いつかなったのですが。

関連するQ&A

  • 入力した任意の数の平方根を求める

    C言語を少しずつですが勉強していて、最小値から最小値までの和を求めるのと、入力した数の2乗を求めるプログラムはわりと楽に完成したのですが、平方根を求めるというのができずに困っています。 プログラムの流れを説明すると、 1.どの処理を行うのか、数字+Enterで選択(平方根は、case 3です) 2.その処理を行う 3.結果の出力 です。 平方根の処理は、 scanfで実数を変数に代入→計算を行う関数を実行→結果を出力です。 症状としては、例えば4と入力して処理を実行すると、桁数のすごく大きい数が入力した数として処理され、また平方根も正しく求められていないようです。 (コンパイル時にエラーは出ていません)

  • 無駄に覚えている数字ってどのくらいあります?

    みなさん、無駄に覚えていて2度と使わないだろうって数字、どのくらいありますか? 私の場合、 ・大学時代の学籍番号 (8ケタx1) ・昔勤めていた会社の部署の内線番号 (8ケタx1、7ケタx1) ・以前住んでいたアパートや家の電話番号 (10ケタx2) ・以前住んでいたアパートや家の郵便番号 (3ケタx1,7ケタx1) ・元カノの実家の電話番号 (10ケタx2) ・元カノの携帯番号 (11ケタx1) ・円周率の 3.141以降の数字 (4ケタ(笑)) もっとも円周率最初の3.14も小中学生の勉強以外に使っていない。 高校受験の時はπでそのまま計算していた。 ・2、3、5の平方根(9ケタx3): 高校の時でも2の平方根は√2 と書いていたので、学校の勉強にすら使っていない。 ざっと思い出せるだけで合計105ケタでした。 (もしかして、今住んでいる家の電話番号も携帯電話に登録しているので覚えている必要ないかも...。) あ、もちろん面倒くさかったら桁数は書かなくてけっこうですよ。

  • 有効数字

     有効数字についての質問です。  計算途中で物理定数を使用するとき、測定値に合わせた桁数まで とればいいことはわかるのですが、そのときに最後の桁はもう一つ下の桁を四捨五入して得た数字を採用するのでしょうか。それとも、元のままの数字を使用するのでしょうか。  例えば、測定値が5桁でこれに円周率をかけるとすると、  測定値×3.1415 なのか、それとも  測定値×3.1416 なのかどちらになるのでしょうか。  初歩的な質問で申し訳ありません。よろしくお願いします。

  • 平方数の数字根

    ある新書で「平方数の数字根は1,4,7,9のいずれかである」と書かれていましたが何故そうなるのかは書かれていませんでした。 「」内は正しいのでしょうか。 また、証明法はどのようにするのでしょうか。 自分でも考えてみたのですがまったく分からず、また検索をかけてみたのですが解答は見つかりませんでした。 よろしくお願いします。

  • 平均値をとると有効数字が増える?

    普通の物差しで測った有効数字3ケタのデータ 2.0[mm] 2.1 2.2 2.1 1.9 2.0 があったとします。各データには±0.1程度の誤差があると考えられます。 これらの合計をとると,和の場合の有効数字は末位が最高位のもの合わせるので,今の場合,0.1位までで計算すればよいので 12.3 となりますよね。これをデータ数6で割りますが,この場合の6というのは正確な6であり,どこまでも6.000…で正しい,有効数字は無限大桁と考えられます。割り算の場合,商の有効桁数は有効数字は有効桁数の少ない方に合わせるので 2.05 となり,現データの2ケタよりも多い3ケタになります。これは正しいのですか?

  • エクセルで平方根を計算する方法は?

    ある数の平方根をエクセル上で計算したいのですが,どのような計算式を入力したらよいのでしょうか?

  • python ver3について

    python3を勉強している初心者です。 参考書に載っていた、階乗を計算する例題を変更したいと思っています。 このプログラムを書き換えて、input文で任意の数字nをキーボードから入力して、結果を表示させたいんですが、どうすれば良いでしょうか。 このプログラムでは思う様に動きません。 n=input() def fact(n):   if n ==0:     return 1   return n*fact(n-1) print(fact(n)) input() よろしくお願いいたします。

  • 平方根で何がわかるの?

    「二乗してその数字になる」、とか三角形の計算とかに平方根を良く使いますが、そもそもなぜ平方根を があるのでしょうか?平方根は計算機ですぐ分かるけどそれが分かると何が解ける? 足し算、引き算、掛け算、割り算、分数、その他いろいろありこれらは実用的ですが平方根は何に使うのでしょうか? 平方根を実用的に使った具体例を猫にでもわかるようにご教授ください。お願いします。

  • 有効数字について

    有効数字の揃え方が分かりません。問題文がそろっていればその揃っている桁数より一つ多く計算して、四捨五入でいいのですか。たとえば、 有効数字2桁に揃えるとすると、4.445=4.5でしょうか、それとも4.4でしょうか。 更に分からないのが、問題文がそろっていないときです。問題集には「多いもの(大きいものではなく)にあわせる」と書いてあります。たとえば、2桁で書かれた箇所が3つ、1桁で書かれた箇所が1つなら、2桁でといつする、と言うことです。でもこの考え方だと1桁の箇所と2桁の箇所が同じ数だけ合ったらどうするのでしょうか。 しかし、先生は「有効数字の低いものに合わせる。箇所の数は関係ない。」と言っていた気がします。上の例なら1桁で書かれた箇所は1つだけだが、低いので1桁で統一する、と言うことです。 かなり混乱して分からなくなっているので、皆さん教えてください。

  • 中学数学 平方根で√のついた数字をa√bにするには

    中学数学の平方根と、三平方の定理を勉強中です。 √25=5や√81=9は単純に一桁の数字の2乗なのですぐ計算できます。 √24の時は、2×12=24、12=2×2×3、√24=2×2×2×3、 √24=2√6というやり方で計算しています。 √24の場合は数字が大きくないのでまだいいのですが、 三平方の定理で大きな数字のルートが出てくると、計算にとても時間がかかってしまいます。 √61のような数字が出てきた場合、√61がこれ以上計算できず、√61のままなのか、 a√bのような形に変えられるのか、ぱっと見て自分でわかりません。 √61のような数字は、ぱっと見てa√bになるのかならないのか 短時間で判別する方法はあるのでしょうか? 自分では判別が出来ずに、無駄に2や3で掛け算をして時間が凄くかかります。 それなのに√61はa√bの形に出来ない数字だったりして、時間を無駄にしてしまいます。 √24の、2×12=24、12=2×2×3、√24=2×2×2×3、√24=2√6というやり方も 頭の中でぱぱっと出てこず、解くのに少し時間がかかってしまいます。 簡単で短時間に計算できる方法はあるのでしょうか? 数学が苦手なので、小学生でもわかるくらい易しく教えてください。

専門家に質問してみよう