電子書籍の厳選無料作品が豊富!

コンパイラはMicrosoft visual C&C++を使用しています。
(1)型指定子のfloat,doubleの大きい数値について。
計算をするとfloatは7桁までは正しくて、7桁より大きい桁はデタラメです。doubleは15桁までは正しくて、15桁より大きい桁はデタラメです。有効数字7桁,15桁とはこういうことでしょうか。
後、floatは有効数字7桁、doubleは有効数字15桁で本当に正しいのでしょうか。
(2)型指定子のfloat,doubleの小数点以下の数字について。
floatは10^-38まで、doubleは10^-308までの数字を扱えると参考書には書いてありますが、計算をしますと小数点以下6桁までは求まりますが、それ以下は求まりまりません。それ以下の数値はすべて0になります。なぜでしょうか。
(3)int,long intとdouble long doubleの違いについて。
intとlong intはともに-2147483648~2147483647までの範囲だと思います。またdoubleとlong doubleはともに有効数字15桁でした。何か違いがあるのでしょうか?

A 回答 (4件)

まだ出ていない内容だけ回答します。



> intとlong intはともに-2147483648~2147483647までの範囲だと思います。またdoubleとlong doubleはともに有効数字15桁でした。何か違いがあるのでしょうか?

C++では、仮に精度や符号の有無などの特性が同じであっても、あくまでも別の型として扱われます。具体的には、多重定義やテンプレートの解決の際に、型の違いが活きてきます。
C++の型は、ある意味で値と同じぐらいの意味を持ちます。
    • good
    • 0

>計算をするとfloatは7桁までは正しくて、7桁より大きい桁はデタラメです。


>doubleは15桁までは正しくて、15桁より大きい桁はデタラメです。

デタラメではありません。「表現可能な範囲での、最も近い値」です。

>(1)型指定子のfloat,doubleの大きい数値について。

IEEE 754-2008の規格に沿った4バイトfloat、8バイトdoubleの場合、仮数部のビット数はそれぞれ24ビット、53ビットです。指数部はそれぞれ8ビット、11ビットです。

floatの仮数部が24ビットの場合、表現出来るのは「(0~2の24乗-1)×(2のn乗)、但しnは-126~+127」です。

doubleの仮数部が53ビットの場合、表現出来るのは「(0~2の53乗-1)×(2のn乗)、但しnは-1022~+1023」です。

floatの場合の「2の24乗-1」は「16777215」ですから、実質的に「0~9999999に、2のn乗を掛けたもの」しか表現できません。つまり「10進数で7桁だけ」が有効です。

doubleの場合の「2の53乗-1」は「9007199254740992」ですから、実質的に「0~999999999999999に、2のn乗を掛けたもの」しか表現できません。つまり「10進数で15桁だけ」が有効です。

>(2)型指定子のfloat,doubleの小数点以下の数字について。
floatで「2の10乗」と「2の-10乗」を足し算するとどうなるでしょうか?

まず、指数と仮数に分けます。「1×2の10乗」と「1×2の-10乗」になります。

次に、指数部を同じにしないと、足し算出来ません。

指数部が小さい方を大きい方に合わせる為「1×2の-10乗」の仮数部を2の20乗で割って、指数部に20を加算します。

「1×2の-10乗」と「0.5×2の-9乗」が等しいのは判りますね。

1を2の20乗で割ると0.00000095367431640625です。-10に20を足すと10です。従って「1×2の-10乗」は「0.00000095367431640625×2の10乗」になります。

2つの数値が「1×2の10乗」と「0.00000095367431640625×2の10乗」になれば、指数部が同じですから、仮数部を足し算できます。

結果「1.00000095367431640625×2の10乗」になります。

これを2進数で書くと以下のようになります。

   1.00000000000000000000×2の10乗
+)1.00000000000000000000×2の-10乗
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   ??????????????
           ↓
指数部が違うので、指数部を同じにする。
           ↓
   1.00000000000000000000×2の10乗
+)0.00000000000000000001×2の10乗
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   1.00000000000000000001×2の10乗

この計算が可能なのは「仮数部が24ビットあったから」です。

では、floatで「2の13乗」と「2の-13乗」を足し算するとどうなるでしょうか?

先ほどと同様に、2進数で書くと以下のようになります。

   1.00000000000000000000000000×2の13乗
+)1.00000000000000000000000000×2の-13乗
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   ??????????????
           ↓
指数部が違うので、指数部を同じにする。
           ↓
   1.00000000000000000000000000×2の13乗
+)0.00000000000000000000000001×2の13乗
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   1.00000000000000000000000001×2の10乗

この足し算の結果をfloatの値にすると、仮数部は24ビットなので、上から24ビットだけが残り、25ビット目以降は「消えて無くなって」しまいます。

と言うより、足し算する前に「仮数部が足りなくて、足す数がゼロになってしまう」のです。

先ほどの2進数の加算で、仮数を24ビットにすると、以下の[]の中身は「精度不足で無くなってしまう」のです。

   1.0000000000000000000000[0000]×2の13乗
+)1.0000000000000000000000[0000]×2の-13乗
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   ??????????????
           ↓
指数部が違うので、指数部を同じにする。
           ↓
   1.0000000000000000000000[0000]×2の13乗
+)0.0000000000000000000000[0001]×2の13乗
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   ??????????????

           ↓
仮数が24ビットなので[]の中身が消えてしまう。
           ↓
   1.0000000000000000000000×2の13乗
+)0.0000000000000000000000×2の13乗
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   1.0000000000000000000000×2の13乗

求まる答えは「ゼロを加算した値」です。

つまり「大きい値に小さい値を足したり引いたりしても、アンダーフローして、ゼロを足したり引いたりしてしまう」のです。

>(3)int,long intとdouble long doubleの違いについて。
>intとlong intはともに-2147483648~2147483647までの範囲だと思います。
それは「intもlong intも、符号1ビット+数値31ビットの、32ビット整数」と仮定した時だけです。

「符号1ビット+数値31ビット」と仮定した時、2の31乗は2147483648なので、正は「1×2の31乗-1」、負は「-1×2の31乗」まで、つまり「-2147483648~2147483647」の範囲を表現できます。

この「数値31ビット」は、float、doubleの「仮数部○○ビット」に相当します。

前述の有効桁数の部分で書きましたが、以下のようになります。

floatの場合「2の24乗-1」は「16777215」です。つまり「10進数で7桁」です。

doubleの場合「2の53乗-1」は「9007199254740992」です。つまり「10進数で15桁」です。

int、long intの場合「2の31乗-1」は「2147483647」です。

すべて「2進数で考えて」下さい。「ホゲホゲ×2のホニャララ乗」が基本です。

この回答への補足

ご回答ありがとうございました。
(1),(3)については分かりました。
(2)についてもう一度お伺いしたいのですが、私が計算した値はとても大きい数ととても小さい数ではなくて10^-8程度の値どうしの演算でした。もう少し正確に言いますと。0.000000という答えでした。
足した値が0になってしまうということではなくて、答えが0.000000になってしまうという状況なのですが、よろしければご回答よろしくお願いします。

補足日時:2009/07/11 15:47
    • good
    • 0

(1)


floatは4バイト、doubleは8バイト
このうち符号、実数部、指数部にビットを割り当てているため
値として持つのはfloatは23bit、doubleは52bitなので
自然と有効桁数は限られます。

(2)
1.024 => 1.024 x 10^0
1024. => 1.024 x 10^4
この違いは指数(10の何乗)だけですよね?
この指数というのが、floatの場合±38、doubleの場合±308ってだけなんです。
だから有効桁数を越えるとすべて0になるのですね。
    • good
    • 0

(1)sizeof(float)やsizeof(double)の値、つまり、


float型やdouble型のために何バイトの領域を割り当てているかによって、
有効数字の桁数は違ってきます。

(2)どんな計算をしましたか?そのときのソースコードを正確に提示してください。

(3)sizeof(int)とsizeof(long int)が同じならば、
int型とlong int型で扱える数値の範囲は同じです。
doubleとlong doubleの関係も同様です。

この回答への補足

回答ありがとうございました。
(2)についてですが以下のようなプログラムを書きました。
#include <stdio.h>
int main()
{
float a,b;
printf("a+b,a-bの計算を行うプログラム。\n");
scanf("%f %f",&a,&b);
printf("a+b=%f,a-b=%f\n",a+b,a-b);
}
a,bの値に0.000000033556 0.000000012556という値を入力したところ
a+b=0.000000 a-b=0.000000という答えでした。
floatをdoubleに変えても同様の答えでした。
ぜひ回答よろしくお願いします。

補足日時:2009/07/11 15:48
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!