あれこれ備忘録@はてなブログ

勉強したことやニュースや出来事を備忘録として書いていきます

このブログには広告が含まれます

気になるJavaの問題を見つけたのでpaiza.IOで試してみた

こんなツイートを見つけた。

int a=1;
int b=++a;
System.out.println("a+b" + a+b);

の答えはどうなるか?という問題である。

本来の狙いはSystem.out.printlnのカッコの中の

"a+b" + a+b

のところが、最初に文字列があるのでそのあとの + 演算子が算術演算子ではなく文字列の連結を意味するという引っ掛け問題だ。

ツイートにはその後のやり取りで答えが書かれていて、ツイートの主によれば答えは

a+b12

だという。

私は引っ掛けに見事に騙されたが、答えが違う気がした。

コードをブラウザ上で実行できるサイトはいくつかあるが、その一つであるpaiza.IOで調べてみることにした。

Web-based online coding environment | paiza.IO

以下が実行結果である。

Web-based online coding environment | paiza.IO

答えは

a+b22

である。

考えてみれば、当たり前で++というインクリメンタル演算子でaの値は1が加算されて2になるはずである。

そして++の位置はaの前なので、bの値はaが2になったあとでそれが代入されたものになる。

とするとaもbも2になる。

ツイッターで間違っていると指摘したのだが、無反応だった。

FF外だから仕方がないかもしれないが。

とりあえず自分の考えが合っていたのがわかって良かった。

この文字列のあとの + が算術演算子にならないという引っ掛けにハマる人は結構多いようだ。

System.out.println("A"+a+b);

System.out.println("A"+(a+b));

とすれば、a+bは数値として加算される。

ちょっと気になった時に、気軽に試せるpaiza.IOは便利だ。

この問題もやってみた。

for文の3番目の書き方がおかしい。

多分、i = i + 2だと思う。

答えの出力の「"答え=“a」もおかしい。

文字列を連結しないといけない。

もろもろ修正して

int b = 9765625;
int a = 0;
    for(int i = 101; i < 1101; i = i + 2) {
        a = b * i;
        if(全ての桁数が奇数か調べる関数(a)) {
            System.out.println("答え = " + a);
        }
    }

これをif文なしで走らせてみたらintが最大値を超えてマイナスの値になってしまう。

Integer (Java Platform SE 8)

intやlongの最大値、最小値 - unsigned

2^31 - 1 = 2147483647

以上はマイナスの値になる。

多分、問題は正の値について考えるのだろうから、aとbはintではなくlongにした。

全ての桁数が奇数か調べる関数(a)をcheck(a)として、関数を作った。

全ての桁数という意味が良くわからないが、各桁の数について奇数か偶数か調べて、全てが奇数ならtrueを、一つでも偶数ならfalseを返すのだと解釈した。

各桁の数を抜き出すには以下のリンクの方法を使った。

複数桁10進数の*桁目だけを抽出したい - C言語・C++・C# 解決済 | 教えて!goo

a = (value % 10);
value /= 10;

1桁目は素直に10で割ったその余りがその数。

2桁目は10で割った答えとそれを10で割った余り。

と順にやっていく。

全部、合わせてこんな感じにしてみた。

public class Main {
    public static void main(String[] args) throws Exception {
        // Here your code !
        long b = 9765625;
        long a = 0;
        for(int i = 101; i < 1101; i = i+2){
            a = b*i;
            if(check(a)) { 
                System.out.println("i = " + i);
                System.out.println("答え = " + a);
            }
        }
    }

    static boolean check(long a) {
        int value = 0;
        boolean isOdd = true;

        while(a > 0) {
            value = (int)(a % 10);
            isOdd = (value % 2 != 0);
            if(!isOdd) break;

            a /= 10;
        }

        return isOdd;
    }
}

実行結果はこれ

Web-based online coding environment | paiza.IO

i = 327
答え = 3193359375

一つしかないらしい。

合っているかどうかはわからない。

久しぶりにJavaをやってみた。

あと

こういうのもあったので、これも試してみたが8.0になった。

Javaのバージョンや実行環境にもよるのだろう。

これも面白かった。

017と書くと8進数を意味する。

なのでaの値は10進数で15(浮動小数点の値を表すdoubleなので正しくは15.0)。

017.0だと通常の10進数の少数になって頭の0は無視される。

だから、a = 15.0とb=17.0を比べるとbの方が大きい。

よってa > b はtrueとなる。

0x17と入力すると16進数を表すので、これは10進数の23になる。

記憶とちょっと違ったのがこれ。

String a = "abc";
String b = "abc";
System.out.println(" a == b : " + (a == b));
System.out.println(" a.equals(b) : " + (a.equals(b)));
System.out.println(" a == \"abc\" : " + (a == "abc"));

これは本来はa == bはfalseになるべきだったはずだと記憶しているのだが、間違っていただろうか?

文字列変数としてのaとbは別なので、a == bはfalseになり、中身の文字を比べるための関数equals()で比べて、trueを得るのだったと思う。

“abc"がプールされて、共通に使われるためにこれを共通に参照するaとbは、a == bでもtrueになってしまうんだったと思う。

a == “abc"も同じか。

String b = new Stirng(“abc”)とするとaとbとは別になるので、a == bはfalseになる。

CodeCampではJavaやAndroid開発などプログラミング言語が勉強できる。無料体験あり