• 締切済み

型指定子についての教えてください。

コンパイラは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桁でした。何か違いがあるのでしょうか?

みんなの回答

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.4

まだ出ていない内容だけ回答します。 > intとlong intはともに-2147483648~2147483647までの範囲だと思います。またdoubleとlong doubleはともに有効数字15桁でした。何か違いがあるのでしょうか? C++では、仮に精度や符号の有無などの特性が同じであっても、あくまでも別の型として扱われます。具体的には、多重定義やテンプレートの解決の際に、型の違いが活きてきます。 C++の型は、ある意味で値と同じぐらいの意味を持ちます。

  • chie65535
  • ベストアンサー率43% (8521/19370)
回答No.3

>計算をすると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のホニャララ乗」が基本です。

gokugokuR
質問者

補足

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

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.2

(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になるのですね。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

(1)sizeof(float)やsizeof(double)の値、つまり、 float型やdouble型のために何バイトの領域を割り当てているかによって、 有効数字の桁数は違ってきます。 (2)どんな計算をしましたか?そのときのソースコードを正確に提示してください。 (3)sizeof(int)とsizeof(long int)が同じならば、 int型とlong int型で扱える数値の範囲は同じです。 doubleとlong doubleの関係も同様です。

gokugokuR
質問者

補足

回答ありがとうございました。 (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に変えても同様の答えでした。 ぜひ回答よろしくお願いします。

関連するQ&A

  • c言語の変数の型について

    浮動小数点数の変数の型ってfloat、double、long doubleがありますよね?(その他もあったら教えてください) doubleはfloatの倍精度らしいですが、倍精度ってのは扱える数字の範囲が2倍なのか有効桁が2倍なのかわからないんで教えてほしいです。ちなみに、doubleとlong doubleの違いも判りません。 あと、これらの変数はprintfで出力するときは最高で8桁までしか出力できないんでしょうか?20桁とかは無理なんですかね?

  • double型からfloat型への型変換について

    double型で-999.999という数字をfloat型へキャストして 少数以下6桁をprintf文で表示すると、それぞれ以下の様になりました。 double -999.999000 float -999.999023 これは、単純にfloatの精度の問題なのでしょうか? また、計算機がどういうルールに基づいて計算をおこなっているということなのでしょうか? 教えてください。

  • 【高校化学】有効数字の指定が無い問題

    【高校化学】有効数字の指定が無い問題 化学の問題などで、答えの有効数字の指定が無い場合がよくあります。 私は小数点以上は上から四桁目を四捨五入、小数点以下は小数以下3桁目を四捨五入で計算しています。 567865465.2255222… →5.68×10^8 21.555555555… → 21.56 1.64233335… → 1.64 しかしこの前、1.111111111…molというのを1.11molとして計算したら問題集の答えと0.001ずれてしまいました。解説では0.111として計算したみたいです。 こういう計算であっているときもあれば、微妙にずれているときも多々あります。 ほんのわずかなズレですが、なんだか気になってしまいます。 さらに計算が続けばもっとズレてしまいそうですし… 特に21.5555…や21.44444など、5や4を四捨五入するのにちょっとためらいます… 私のやりかたはあっているでしょうか? 入試ではさすがにバツになりませんよね? ご回答よろしくお願いします。

  • 型について

    Cの型の中にint と long int がありますけどこの違いは何なのでしょうか?本にはどちらも4ビットの整数(long intは長整数となっていますが)-2147486648~2147483647となっていますが・・。 同様にdouble と long double は何が違うのでしょうか? 初歩的なところですがよろしくおねがいします。

  • 型変換??

    int RANDOM_FUNCTION( int n ) { return (int)( rand() / (float)RAND_MAX * n ); } について Q1.この関数は0からn-1までの乱数を作るそうなのですが,何故ですか? 0<=rand()<=RAND_MAX だから0からnまでの乱数ができるような気がするのですが. Q2.RAND_MAXではなく(float)RAND_MAXとキャストしてある意味は何ですか? Q3.srand((unsigned)time(NULL));と srand((unsigned int)time(NULL));では何か違いますか? Q4.  static int first = 0; if (first == 0){ srand((unsigned)time(NULL)); first = 1; } という処理でsrand((unsigned)time(NULL));は最初の一回だけ呼び出されるようになっているようですが,この部分を srand((unsigned)time(NULL)); というように毎回呼び出すようにするとどうなりますか? 一回呼び出すだけで乱数系列の初期値が呼び出される時に変化しているのですか? Q5.この関数とは関係ない質問ですが,例えば a:int型 b:int型 c:double型 d:float型 のとき d = a / b + c という演算は 1 a:int型,b:int型より(a / b)の結果はint型(小数になった場合は小数点以下切り捨て) 2 (a / b):int型,c:double型,int<doubleより (a / b + c)の結果はdouble型 3 d:float型,『=のあるときは左辺の型に合わせる』よりdはfloat型 というように型変換されているという解釈でいいのでしょうか??

  • 変数の型について

    変数の型を設定する時ですが、浮動小数点とは何ですか? doubleとfloatはどう使い分けるのですか?

    • ベストアンサー
    • Java
  • C言語による演算時の誤差について

    C言語初心者でどなたかご教授お願いします。 小数点の演算を行うわけではないのですが、 演算を行う数値が大きすぎるために、double型を使用して以下の計算を行うつもりです。 計算結果はlong型(小数点以下切り捨て)です。 double a,b,c; long x; x = (long)((a*b/c/100) 例)  x=(long)((189000*105000/100000)/100) 上記のような計算を行った際でも誤差が発生する可能性があるのでしょうか?

  • エクセルで有効桁を指定して丸める

    以前、↓↓にて http://oshiete1.goo.ne.jp/qa1345491.html 「excelで普通に四捨五入をするとなると  『ROUND』などで小数点以下の桁数を指定しますよね。  そうではなく、有効桁数3桁で四捨五入…例えば、  0.1234ならば0.123  1.234ならば1.23  12.34ならば12.3  123.4ならば123…のように  数字を四捨五入させる関数(?)はあるのでしょうか。」 と質問し、 =ROUND(A1,-INT(LOG(A1))-1 + 3) とか =VALUE(TEXT(A1,"0.00E+00")) といった方法を教えていただいたのですが、 0.1234 なら 0.123 ・・・ 123.4 なら 123 までは同じなのですが、 1234.5 なら 1230ではなく1235 12345.6 なら 12300ではなく12346 つまり、1000未満の場合は以前と同じく有効数字3桁で 1000以上の場合は小数点以下四捨五入としたい場合は、 IF関数で =IF(1000>A1 ・・・のように条件指定してやるしかないのでしょうか。 (A1の部分にも長々した数式が入るもので) 数式がかなり長くなってしまい、見づらいので なにか良い方法があればと思ったのですが…

  • エクセル(Excel)で、数値を一定の有効数字で表示したいのですが…

    エクセル(Excel)の書式設定の表示形式では数値を選択すると、小数点以下の桁数を揃えることができますが、同じ感覚で有効数字を一定にして表示させるにはどんな方法があるでしょうか? 例えば、0.01234、0.1234、1.1234、11.1234、111.1234という五つの値を、有効数字3桁を指定して表示して、順に0.0123、0.123、1.12、11.1、111という風に自動的に表示してくれる表示形式、あるいは関数を探しています。 事務計算で小数点以下何桁というのが重要であるように、技術計算ではこのように有効数字を揃えたい場合が多いと思いますので、どなたかご存じの方、お教えください。 なお、指数形式では似たような結果になりますが、わかりにくい表示なので使いたくありません。 よろしくお願いいたします。

  • EXELで小数点以下の管理

     ある関数の計算結果の小数点以下を切り捨てた数値を出したいのですが、セル一つ一つにINT関数を付け足していく以外の方法はありませんか?  “指定した範囲内の数値は全て小数点以下を切り捨てる”みたいな設定とか。   セルがかなり大量で困ってます。宜しくお願いします。

専門家に質問してみよう