ループの謎まとめ
5980 ワード
1.タイプ変換時の問題
質問:byte b=(byte)0 x 90;どれくらいですか. -112
分析:
(1)intが32ビット、byteが8ビット
(2)一方、0 x 90は8ビットで表すように見えるが、byteは符号数があるため範囲が-128~127、0 x 90は144である、byteで表すと最上位に位置されるため-112である.
まとめ:
ブレンドタイプの比較や割り当ては避けます.
public class PuzzlerDemo24{
public static void main(String args[]){
byte by = (byte)0x90;
System.out.println(by);
for(byte b=Byte.MIN_VALUE;b<Byte.MAX_VALUE;b++){
if(b == (byte)0x90){
System.out.println("Joy!");
}
}
}
}
2.増分操作の戸惑い
質問:int j=j++;jはいくらですか.もとの値
分析:
(1)j++の実行プロセス:jの値は1を加算しますが、元の値を返します.
(2)j=j++のプロセス:
int tmp = j; j = j+1; j = tmp;
したがってjは元の値である.
まとめ:
同じ変数に対して1つの式に複数回値を付けないでください.
public class PuzzleDemo25{
public static void main(String args[]){
int j = 0;
for(int i=0;i<100;i++){
j++;
}
System.out.println(j);
}
}
3.intの議論
(1)intの取値範囲:-231~231-1であるため、取値範囲は非対称である.
(2)Integer.MAX_VALUE:Integer.MAX_VALUE+1はIntegerに等しい.MIN_VALUE;したがって、この値を超える整数はあり得ません.
(3)Integer.MIN_VALUE:intの最小値で、彼の負数は元の値で、変わらない.
(4)intは境界があり,Floatのように境界が存在しない.
機能:
(1)Integer.MAX_VALUE+1==Integer.MIN_VALUE;
(2)1つの値がIntegerの境界付近にある場合はlong値を使用することが望ましい.
(3)符号のある整数タイプについては,負の値の合計が正の値より1つ多い.
public class PuzzleDemo26{
public static final int END = Integer.MAX_VALUE;
public static final int START = END - 100;
public static void main(String args[]){
int count = 0;
for(int i=START;i!=END;i++){
count++;
}
System.out.println(count);
}
}
4.浮動小数点数の検討
質問:
double i =Double.POSITIVE_INFINITY;
i=i+1はtrueですかfalseですか?
分析:
(1)大きな浮動小数点数とその後継との間には間隔があり,この間隔は大きく,無限大と後継の間隔は無限大である可能性がある.
(2)十分大きな浮動小数点数に1を加えると値は変化しない.1は2つの浮動小数点数の間の隙間を補うことができないからである.
(3)ulp(Unit in the last place):2つの浮動小数点数の間の空隙.java.lang.Math.ulp(double d)はdのulpがいくらであるかを計算することができる.
まとめ:
(1)バイナリ浮動小数点算術は実際の算術に対する近似にすぎない.
(2)小さな浮動小数点数を大きな浮動小数点数に加算した場合、大きな浮動小数点数の値は変更されない場合があります.
浮動小数点数の特徴:
1.浮動小数点数で無限大、無限小を表すことができる.POSITIVE_INFINITYとNEGATIVE_INFINITY
2.Double.NaN:数ではないので、彼はどんな数値と比較しても等しくありません.彼自身も含まれています.
public class PuzzleDemo28{
public static void main(String args[]){
double d = Double.POSITIVE_INFINITY;
System.out.println(" :" + Math.ulp(d));
System.out.println("d d+1 :" + (d==d+1));
}
}
public class PuzzleDemo29{
public static void main(String args[]){
double i = Double.NaN;
while(i!=i){
System.out.println(" !");
}
System.out.println(" !");
}
}
5.シフトオペレータの検討
一、問題:-1<<32はいくらですか. -1
分析:
(1)-1はint値なので32ビットあります.
(2)左操作数がintタイプである場合、右操作数の5ビットを切り取る.すなわち、右操作数は必ず32未満である.左オペランドがlongタイプである場合、右オペランドの6ビットを切り取る、すなわち右オペランドは必ず64未満である.
(3)上記例の右操作数が32であれば、左操作数は変わらない.
(4)上記例の右操作数が32を超えると、右操作数に余裕をとる必要がある.
二、問題:-1<-1はいくらですか. -1<<31
結論:
(1)右シフトオペレータは常に右シフトの役割を果たし,左シフトオペレータは常に左シフトの役割を果たす.
(2)負のシフト長は、5ビットだけ低くすることにより正のシフト長となる.
(3)シフトオペレータを用いて,1つの数値の全てを一度にシフトすることは不可能である.
public class PuzzleDemo27{
public static void main(String args[]){
System.out.println("-1>>32:" + (-1>>32));
System.out.println("-1>>>-1:" + (-1>>>-1)); //
System.out.println("-1>>-1:" + (-1>>-1));
}
}
/*
-1>>32:-1
-1>>>-1:1
-1>>-1:-1
*/
6.ありえない事実
質問:i<=j&&i>=j&&i!=jはtrueを返しますか?i = new Integer(0),j = new Integer(0)
分析:
(1)数値タイプではダメに違いありません.
(2)i!=j:i,jが基本データ型の場合は値比較を表し、参照データ型の場合はオブジェクト参照比較を表す.
(3)jdk5.0には自動梱包と解体機能が追加する.
結論:
両方のオペランドがパッケージされた数値タイプである場合、数値比較オペレータは値比較を行い、判断オペレータは参照識別比較を行う.
7.「+」の重荷
質問:i=i+0ですか?必ずしも
分析:
(1)Stringタイプでは+が接続を表し,iがStringであれば文字列接続を表す.
結論:
"+"オペレータには、次の2つの機能があります.
(1)数値計算.
(2)文字列接続.
public class PuzzleDemo30{
public static void main(String args[]){
String i = "a";
while(i!=i+0){
System.out.println(" !");
}
System.out.println(" !");
}
}
8.複合オペレータの再来襲
質問:i>>=1以降iの値は変わらない可能性がありますか?かもしれません.
分析:
(1)>>>=解析:a>>>>=bはa=(TypeA)に等価である(a>>>b);
(2)例:
short i = -1 i = 0xffff;
int j = i; j = 0xffffffff;
j>>>=1; j = 0x7fffffff;
i = (short)j; i = 0xffff;変わらない.
public class PuzzleDemo31{
public static void main(String args[]){
short i = -1;
while(i!=0){
i>>>=1;
}
System.out.println(" !");
}
}
9.パッケージクラスの比較オペレータと判定オペレータ(==または!=)
判定オペレータ
(1)基本タイプの場合は値比較を表す.
(2)参照データ型については,Integerなどのパッケージクラスを含むオブジェクト参照比較を示す.
まとめ:
両方のオペランドがパッケージされた数値タイプの場合、数値比較オペレータは実行された値比較であり、判断オペレータは参照識別比較を実行する.
1つがパッケージされた数値タイプであり、もう1つが基本タイプである場合、判定オペレータは値比較を実行します.
public class PuzzleDemo32{
public static void main(String args[]){
Integer i = new Integer(1);
Integer j = new Integer(1);
while(i<=j && i>=j && i!=j){}
System.out.println(" !");
}
}
10.精度損失が発生する3つの拡張基本タイプ変換
(1)int-->float:
(2)long-->float:
(3)long-->double:
public class PuzzleDemo34{
public static void main(String args[]){
final int START = 2000000000;
System.out.println(Math.ulp((float)START));
int count = 0;
for(float f=START;f<START+50;f++){
count++;
}
System.out.println(count);
}
}
10.ハートマジック数!
マジック数の定義:一部のプログラムコードでは、プログラマはコードに現れるが説明されていない数値定数または文字列をマジック数(magic number)またはマジック文字列と呼ぶことが多い.
提案:すべての魔数の代わりに適切な名前の定数を使用します.