• ベストアンサー

整数の出力について

Cを学習を始めたばかりのものですが、int と unsinged int のことで少しわからないことがあります。 int plus3 = 3, minus3 = -3; double ddt1, ddt2; と変数宣言し、 main関数で ddt1 = minus3 + 1; ddt2 = minus3 + 1U; として出力したところ ddt1は-2.0 ddt2は4294967294.0 となりました。 ddt1の結果はわかるのですが、ddt2はなぜ 4294967294.0 になるのでしょうか? 1Uの効果でunsinged型にあわせて計算しているのでしょうか? もしそうだとしたら minus3 が 4294967293 になると思うのですが、なぜminus3 が 4294967293 になるのでしょうか? 説明が不足ならまたつけたしますのでどうか教えてください。

質問者が選んだベストアンサー

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

169という数値を例とします。 169 =100+60+9 =1*100+6*10+9*1 =1*(10の2乗)+6*(10の1乗)+9*(10の0乗) となります。 各々の「a*(bのc乗)」に着目します。 a:もとの数値の各桁の数字 b:10で固定(だから10進数といいます) c:いちばん右から0、1、2と増えていく ここで、0169という表記のことを考えます。途中を省略すると、 0169 =0*(10の3乗)+1*(10の2乗)+6*(10の1乗)+9*(10の0乗) となります。 最初の項である「0*(10の3乗)」は、「0に何を掛けても0」という原則から0です。 その結果、 1*(10の2乗)+6*(10の1乗)+9*(10の0乗) =0*(10の3乗)+1*(10の2乗)+6*(10の1乗)+9*(10の0乗) となり、169=0169となります。 同様に、00169も、000169も、0・・・0169も、すべて「百六十九」です。 話を元に戻します。 2進数の 010101010 と 10101010 が同じかどうか、という話でした。 答えは、もうおわかりですね。

shomarket
質問者

お礼

そうゆことだったんですか。なるほど。よく見れば 010101010 は10101010 の前に 0 が付いているだけですね。 こんなに長く質問に付き合っていただき、ほんとうにありがとうございました。説明もとてもわかりやすく、いい勉強ができました。

その他の回答 (6)

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

>int a = 011; 「C言語では」先頭にゼロを付けると、8進数であるとみなすことになっています。 したがって、この値が10進で9になるのは正しいです。 先の回答で書いたのは、一般的な世界において、10進の 169 0169 00000000169 は同じですか?異なりますか?という話です。

shomarket
質問者

補足

よくわかりませんが、同じ値になると思います。よろしければ詳しくこのことを教えていただけませんか?

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

>010101010 と 10101010 は同じなのでしょうか? 十進数において、 169 0169 00000000169 これらの数値は同じ値を持ちますか?異なる値を持ちますか?

shomarket
質問者

補足

間違っていたらごめんなさい。異なる値をもつと思います。なぜなら実際に プログラムを作り int a = 11; と宣言し、printf("a=%d", a)で出力すると a=11 と出ますが int a = 011; と宣言して、printf("a=%d", a)で出力するとなぜか a=9 と出てきてしまうからです。

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

>実際になぜ 010101001 + 1 = 010101010になるのかよくわかりません。 二進数の計算について、どの程度の知識をお持ちですか?

shomarket
質問者

補足

二進数を十進数に直す程度です。010101001は十進数にすると169になると思います。そう考えると010101010は170になると思うのですが、170を二進数にすると10101010となり少し混乱しています。 010101010 と 10101010 は同じなのでしょうか?

  • hashioogi
  • ベストアンサー率25% (102/404)
回答No.3

使用されているC言語の教科書に「暗黙の型変換」という項目があれば、そこを読まれたらいかがかと存じます。

  • qbr2
  • ベストアンサー率50% (62/123)
回答No.2

コンピュータでマイナスの値を保持する場合には、一般的に 「2の補数」の形式が用いられます。 詳細は割愛しますが、簡単に言うと 正の数のビットを反転して1を足すと負の数になります。 int型のデータサイズは、32ビットなので、 +3を2進数で表現すると、 00000000000000000000000000000011 -3は、+3を反転させて 11111111111111111111111111111101 -3を、負の数ではなく正の数として10進数にすると、 4294967293になります。 補数とは何か?なぜ補数表現を用いるか?等は、 情報処理試験でもよく問われる内容ですし、プログラミングの基礎ですので、 この機会に、勉強されると良いかと思います。

shomarket
質問者

補足

>-3は、+3を反転させて 11111111111111111111111111111101 とあるのですが、 11111111111111111111111111111101 というのは+3を反転して 11111111111111111111111111111100 にしたものに1を足した結果なのでしょうか? もうひとつ伺いたいことがあるのですが、 ウィキベィアで 補数ついてよんだのですが、"2 の補数を求めるには、1 の補数に 1 を加算するとよい。" とあります。 "2 進法 101010110 と表される数に対する 1 の補数は 010101001 である。" これはわかるのですが実際になぜ 010101001 + 1 = 010101010になるのかよくわかりません。これは 010101001 + 1 で 1 + 1 最下位ビットが繰り上がりして隣のビットが1になるのでしょうか? 説明不足であればまた付け足しますのでよろしくおねがいします。

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

>1Uの効果でunsinged型にあわせて計算している そうです。 minus3 はint型(signed int型)、1Uはunsigned int型です。 両者を使って演算する際、型をunsigned intにそろえる動きをします。 int型のminus3の内部表現(メモリー中の0と1のパターン)を 16進で書くとFFFFFFFDです。これをunsigned int型とみなすと、 お書きになったとおり4294967293となります。 minus3はあくまでint型の-3です。これは変わりません。 内部表現をint型とみなすかunsigned int型とみなすか、という話です。

関連するQ&A

  • froat型

    int型の変数iとjに100000000を代入し、float型の変数rを宣言し、   r = (i + j + 1); を計算するとrは200000000.000000になりdouble型の変数uを宣言し、   u = (i + j + 1); を計算するとuは200000001.000000になりました。 何故そうなるのかわかりません。教えてください。

  • 引数のみで出力

    問題として main内部を変更してはならない。 関数sub()でmainのループと同じ出力するようにせよ。 ただし、関数subで引数以外の変数を宣言してはならない。 また、広域変数を追加してはならない。 となっていて、色々とforループで出力させようと 配列にしたりポインタにしたりしたのですが forのiに比例する配列をどう組めばいいのか、わからないです。。。 mainの出力は 1 8 15 22 29 36 となっています。 これをsubでもできるように設定するみたいです。 #include <stdio.h> #define MAX 7 void sub(int [MAX]); int main() { int i; int x[MAX]; for (i = 0; i < MAX-1; ++i) { x[i] = 7*i+1; } x[MAX-1] = 0; for (i = 0; x[i] > 0; ++i) { printf("x = %d\n", x[i]); } printf("print again\n"); sub(x); return 0; } void sub(int a[MAX]) { // a[6]=0 // MAX 7 a[MAX-1]=0; for(a[MAX-1];a[MAX-7]<=MAX-1;++a[MAX-1]){ //a[MAX-1] = 7*a[MAX-1]+1; printf("a[%d] = %d\n",a[MAX-1],a[MAX-7]); } }

  • ・関数内で宣言された変数の扱い(C入門本の説明で)

     以下C言語入門書の説明ですが!  いまいちわかりません?   ・関数内で宣言された変数の扱い 関数内で宣言した関数は、その関数内でのみ有効な変数になります。関数が異なれば、同じ変 数名で宣言することができます。例えば、main関数と(?)kansuu関数で、同じ(?)hennsuuという名 前の変数を宣言することができます。  int main() { int (A)hensuu = 0; (B)kansuuu(1); } int (C)kansuu(int hikusuu) { int (D)hensuu = 10; }  列のmain関数で宣言されている(?)hensuuと、さ(?)kansuu関数で宣言されている(?)hensuuは 同じ名前ですが、独立した異なるものです。(?)kansuu関数が実行されているときに、(?)hensuuの値 を変更しても、main関数で宣言されている(?)hensuuの値は変更されません。 また、(?)kansuu関数を実行している間だけ、(?)kansuu関数で宣言されている(?)hensuuが有効です。 (?)kansuu関数から呼び出し元でるmain関数に戻った際は、(?) kansuu関数で宣言した (?)hensuuはもう有効ではなくな、値を参照することもなくなります。     以上の説目で、   (A)hensuu、 (B)kansuuu、(C)kansuu、(D)hensuu  (アルファベット)を分かりやすいよう追加しました。   説明の   (?)にプログラムの(A)~(D)をつけたらどうなるか知りたいです。 (何となくわかるですが?)   よろしくお願いします。

  • 階乗の出力について

    Cを勉強中の者です。再起コールを使った階乗計算の結果を出力するプログラムをつくったのですが、もし再起コール(関数 kaijyo)を使わずにfor文などを使って同じように、階乗計算を行いたい場合どのようにすればいいでしょうか? 以下がそのソースコードです。説明が不足であればまた付け加えますのでよろしくおねがいします。 #include <stdio.h> int kaijyo(int a); int main(void) { int a; a = kaijyo(6); printf("6! = %d\n", a); return 0; } int kaijyo(int n) { if(n == 1) return 1; else return n*kaijyo(n-1); /*これを使わずに6!の結果を出したい/* }

  • コンストラクタで設定した値が表示されない

    以下のプログラムを見ていただけたら分かるとおり、コンストラクタで設定した値が、配列だと表示されるのに、配列を使用していない変数だと表示されません。なせなのでしょうか? よろしくお願いします。 package test; public class test { public test(int[] idt, double ddt, String title) { title = "テスト"; ddt = 99.9; for(int i=0; i<idt.length; i++) { idt[i] = i; } } public static void main(String[] args) { int[] idt = {0, 0, 0}; double ddt=0.0; String title= ""; test t = new test(idt, ddt, title); for(int i=0; i<idt.length; i++) { System.out.println(idt[i]); } System.out.println(ddt + ", " + title); } }

    • ベストアンサー
    • Java
  • for文初期化で整数と実数を混在させると値が狂う

    C++ではfor文の初期化時にカウンタ変数等の宣言ができますよね. 0°から360°を表示するプログラムの例なのですが,次のコードを見てください. int main(void) { const double drad = 2 * M_PI / 6; double rad; rad = 0.0; for (int i = 0; i <= 6; i++, rad+= drad) { // cout << "rad: " << rad << endl; cout << "deg: " << rad * 180.0 / M_PI << endl; } } このプログラムを実行すると,0°から60°ごとに360°まで表示されました. ここで,for文の初期化処理でradの初期化を行おうとして, for (int i = 0, rad = 0.0; i <= 6; i++, rad+= drad) とプログラムを書き換えたところ,表示値は deg: 57.2958 deg: 114.592 deg: 171.887 deg: 229.183 deg: 286.479 deg: 343.775 となりました. また,コメントアウトしてある行を有効にしてradの中身を直接表示させると, rad: 0 rad: 1 rad: 2 rad: 3 rad: 4 rad: 5 rad: 6 といったように,radが整数値に丸められています. int iをfor文の外で宣言して for (i = 0, rad = 0.0; i <= 6; i++, rad+= drad) としたときには,正しい角度の表示が行われました. これは,for文の初期化時に変数宣言を行うとき,同時にほかの初期化処理を記述してしまったらその変数も同じ型の新しい変数として宣言されてしまうということなのでしょうか? for (int i = 0, rad = 0.0;... →int i と int rad がスコープ内の変数として新しく宣言される?

  • init関数の意味

    C言語をメインで学習しているのですが、 よく変数の初期化のためにわざわざinitという関数を作って、それをmainの中で実行しているサンプルを見ます。 これだと変数はグローバル変数として宣言しなければいけませんし、init関数なんて作らなくても普通に変数をmainの中で宣言して、同時に初期化すれば良いのではと思ってしまいます。 一体何のためにわざわざinit関数を作るのでしょうか? また、別の質問なのですが、ポインタを使えばグローバル変数を使う必要はないような気がしていて、逆にポインタを使うのが面倒なときでも、グローバル変数で代用できてしまう気がします。 それぞれを使うときのメリット、デメリットがあれば教えていただきたいです。

  • 数の大小の出力

    C言語で関数を用いたプログラムを作成しているのです、行き詰まっています。内容は、double型の数を2つ入力して大きい数を出力するというものですが、エラーは1つもでてはいないのですが結果が0と表示されてしまいます。私の書いたプログラムに問題点はなんなのか教えていただけないでしょうか? ちなみに、このプログラムの条件は ・main関数は値の入力と関数を呼び出し、結果を出力する。 ・大小を判別する部分は関数として作成。 ・関数の引数は入力した2つの値。 ・関数の戻り値は大きいと判定した数。となっております。 ちなみに私の書いたプログラムはこちらです。条件とあわせて指摘をおねがいいたします。 #include<stdio.h>  double daisyou(double x, double y);  int main(){  printf ("数を入力してください。");  scanf("%f %f",&a,&b);  max = ookii;  printf("大きい数は%f\n",max);  }  doubele daisyou(double x, double y){  double ookii;  if(x>y){  ookii = x;  returun ookii;  }else if(x<y){  ookii = y;  return ookii;  } }

  • mainの外に変数 vs ポインタ渡し

    C++についての質問です。プログラミング初心者ですが、よろしくお願いします。 最近、関数の外側でも変数を宣言できることを知りました。関数の外側で変数を宣言すると、全ての関数でその変数にアクセスすることができ大変便利なように思います。 「わざわざポインタ渡しなどする必要はないのでは?」と思ってしまいました。 これは何か問題があるのでしょうか? 初心者の言葉で説明しても理解しにくいかと思いますので、例として「足し算するプログラム」を以下に記載します。 ポインタ渡しで書くと、以下のような感じになるかと思います。 //●ポインタ渡し #include "stdafx.h" #include <iostream> void func(int x,int y,int *pans){ *pans = x+y; } void main(){ int a=10, b=20, ans; func(a,b,&ans); std::cout << ans << std::endl; } しかし、mainの外に変数を宣言すれば //●mainの外に変数 #include "stdafx.h" #include <iostream> int a,b,ans; void func(int x,int y){ ans = x+y; } void main(){ a=10; b=20; func(a,b); std::cout << ans << std::endl; } ansをポインタ渡しする必要なく、funcの計算結果をansに代入できました。 「●mainの外に変数」のプログラムはどのような問題や危険性を孕んでいるのでしょうか? 以上になります。長文お読みいただきありがとうございました。 よろしくお願いいたします。

  • C++ ポインタ初級

    C++で、自作関数内でメインの数字をインクリメントします。 自作関数はVOIV型でやりたいんです。 #include <stdio.h> void plus( int * ); main( ){  int a = 1;  int *&p = &a;  plus( p );  printf( "%d" , *p ); } void plus( int *i ){  ( *i )++; } int型の変数を2つ宣言したけど、1つでやる方法はないですか? #include <stdio.h> void plus( int * ); main( ){  int a = 1;  plus( &a ); // aのアドレスを渡して、  printf( "%d" , a ); } void plus( int *i ){ // アドレスの値を  ( i )++; // インクリメントしたつもりだけど } 結果は1のままでした。