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

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

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

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

4717閲覧

C++ 小数500桁の全ての文字列を得る方法はありますか?

opyon

総合スコア1009

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/11/02 02:07

編集2018/11/02 04:22

###解決!
回答くださった方ありがとうございました。

参考情報:多倍長浮動小数点数

@tiitoiさんの回答より

C++

1#include <boost/multiprecision/cpp_dec_float.hpp> 2 3namespace mp = boost::multiprecision; 4// 仮数部 500 bit の浮動小数点数 5using cpp_dec_float = mp::number<mp::cpp_dec_float<500>>;

###知りたいこと
タイトルのとおりですが、例えば1/7=0.1428571428571428...
これを全て文字列として小数点以下500桁欲しいのですがSTLのlong double型ですと正確な値は16桁までしか取得できません。
何か良い方法があればご教示頂けると助かります。

###サンプルコード

C++

1#include <cstdio> 2#include <iostream> 3#include <iomanip> 4 5int main() 6{ 7 long double x; 8 for (int i = 1; i < 10; ++i) 9 { 10 x = 1.0 / i; 11 std::cout << i << " " << std::fixed << std::setprecision(20) << x << std::endl; 12 } 13 getchar(); 14 return 0; 15} 16// 出力例 17// 1 1.00000000000000000000 18// 2 0.50000000000000000000 19// 3 0.33333333333333331483 20// 4 0.25000000000000000000 21// 5 0.20000000000000001110 22// 6 0.16666666666666665741 23// 7 0.14285714285714284921 24// 8 0.12500000000000000000 25// 9 0.11111111111111110494 26

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

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

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

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

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

guest

回答3

0

ベストアンサー

小数点以下500桁欲しい

浮動小数点数の桁数は、仮数部のビット数で決まります。
IEEE754 という規格で単精度 (C++ の float 型) では23ビット、倍精度 (C++ の double 型) では52ビットと決められています。

log_10 2^23 = 6.923689900271567
log_10 2^52 = 15.653559774527022

では、10進50桁を表すのに2進で何ビット必要なのか考えると、1661 ビットあればいいことがわかります。(ケチ表現で1660ビット)

log_{10} 2^x = 500 2^x = 10^{500} x = log_2{10^{500}} = 1660.96404...

boost::multiprecision

boost の multiprecision ライブラリで多倍長浮動小数点演算が行えます。

以下で仮数部を指定したビット数の浮動小数点数を作成できます。

mp::number<mp::cpp_dec_float<ビット数>>

基数は10なので、500桁表したい場合はそのまま500とすればよいです。
ただし、ケチ表現により実際はビット数 + 1 桁を表すことができます。

cpp

1#include <iostream> 2 3#include <boost/multiprecision/cpp_dec_float.hpp> 4 5namespace mp = boost::multiprecision; 6// 仮数部 500 bit の浮動小数点数 7using cpp_dec_float = mp::number<mp::cpp_dec_float<500>>; 8 9int main() 10{ 11 cpp_dec_float a = 1.; 12 cpp_dec_float b = 7.; 13 cpp_dec_float result = a / b; 14 15 // 桁数 16 std::cout << "digits: " 17 << std::numeric_limits<decltype(result)>::digits10 + 1 18 << std::endl; 19 // 値 20 std::cout << std::setprecision( 21 std::numeric_limits<decltype(result)>::digits10 + 1) 22 << result; 23}
digits: 501 0.14285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714

投稿2018/11/02 03:26

tiitoi

総合スコア21956

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

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

opyon

2018/11/02 04:13

回答ありがとうございます。 質問に書こうか迷っていたのですが、また別質問になるので敢えて要件だけにして質問していました。 boostのリファレンスにある下記を実装してエラーで躓いて利用を断念していました。 mpfr_float_500 仮数部が500ビットの浮動小数点数型 cpp_dec_floatの方を使って定義すれば良かったのですね。 実装例をサンプルコードで提示して頂けたのでどのように使うかの理解が深まりました。
tiitoi

2018/11/02 04:20

mpfr_float は外部ライブラリ MPFR library を使うものなので、使うにはそちらを導入しておく必要があります。 cpp_dec_float は boost::multiprecision の実装を使うので、外部ライブラリなしに使えます。
opyon

2018/11/02 04:23

なるほど!そういうことでしたか! 使えないものを使おうとしていたのですね^^; これまた理解が深まりましたありがとうございます。
guest

0

500桁分の数値の配列から10進演算するクラスを作りましょう
加減乗除を実装する必要はありますが、そんなに難しくはないですよ

投稿2018/11/02 02:23

y_waiwai

総合スコア87719

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

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

opyon

2018/11/02 04:15

回答ありがとうございます。 そもそもある桁数以上の桁が取り出せないのです。
y_waiwai

2018/11/02 04:18

まあ、拡張した浮動小数点使うのもいいですが、10進<>2進の変換のところで満足できないところがでてきそうなきがします
opyon

2018/11/02 04:26

取り敢えず1000桁必要な問題まで解けたので今回の要件では大丈夫そうです。 速度重視とかまた別の条件や要件があるとクラス実装なども考慮する必要が出てくるかも知れませんね。 その時はまた質問させていただきたいと思います。
guest

0

筆算の方法で計算すればいいと思います。

投稿2018/11/02 02:22

Zuishin

総合スコア28656

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

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

Zuishin

2018/11/02 02:27

整数部の 1 を 7 で割ると 0 余り 1 です。 なので "0." という文字列がまず得られます。 余りの 1 を 10 倍して 7 で割ります。 1 余り 3 なので "0." に "1" を連結します。 余りの 3 を 10 倍して 7 で割ります。 4 余り 2 なので "0.1" に 4 を連結します。 以下同じようにループしてください。
opyon

2018/11/02 04:16

回答ありがとうございます。 筆算での実装は質問後に試して出来ていました。 ただあまりにも愚直なのでどうなのかなと思っていたところです。
Zuishin

2018/11/02 04:26

boost::multiprecision の存在は私も知っていましたが、それを導入しなくていいのと、実装が簡単で高速軽量でメモリ使用量も少ないので、あえてこちらの方法を勧めました。
opyon

2018/11/02 04:32

なるほど。そうだったんですね。 速さ軽さが必要になる場合には筆算も選択肢になると覚えておきます。
Zuishin

2018/11/02 04:34

愚直で悪いことは何もないと思いますね。愚直な方法をとった結果、効率が悪くなるならデメリットですが、そうでないなら愚直を恐れる必要はありません。 私が多分この質問を自分で解決するなら、恐らく PowerShell か何かで結果の数字を作ってファイルに保存し、運用ではそれを読み出して使います。
Zuishin

2018/11/02 04:37

念のため。高速計量というのはあくまで「実用上問題になることはないであろう」ということで、boost::multiprecision と比較したことはありません。
opyon

2018/11/02 04:38

>効率が悪くなるならデメリットですが、そうでないなら愚直を恐れる必要はありません 目からウロコです! 愚直を恐れず、ライブラリに頼らず(多分頼る)、精進します。
opyon

2018/11/02 04:39

>高速計量というのはあくまで「実用上問題になることはないであろう」 お気遣いありがとうございます。 問題を解くレベルの実装ですので大丈夫です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問