naoppy-jyokenの日記

Javaで競プロをするぞ、NITAC情研用

Java入門1

ようこそ

これからプログラミング初心者を対象に、Javaでのプログラミング入門をする記事です。

Javaの環境構築

プログラミングをするには、プログラミングに必要な実行環境開発環境をパソコンに入れて、設定をする必要があります。

ただ、これは初心者には難しく、また、権限がないパソコン(学校のパソコンなど)に設定することはできません。自分のパソコンを持っていない人のために、オンラインでプログラミングをして、書いたプログラムを実行するサイトがあるので、しばらくはそれを使います。

Code, Compile & Run | CodeChefにアクセスして、ポップアップにJAVAと入力して、選択してください。

f:id:naoppy_ac:20181129230347p:plain

このサイトは入力の補完機能があるため、長いコードを一々全て打つ必要がなく、とてもプログラミングがしやすいのでオススメです。 最初に入力されているコードは気にしなくて大丈夫です。

PG BATTLE 2019 に参加しました

私は明石高専チームで参加し、難易度ましゅまろを担当しました。 余裕やろ~と思っていたら割とDが難しくてびっくりしました。

結果は3完です。4問目なのですが、Kotlinが使うJava-runtimeのバージョンが手元の環境と違っており、CEで通りませんでした。 CE回避したら通ったのでコードテストをしなかった(する時間が無かった)ことを悔やんでいます。

f:id:naoppy_ac:20190928160813p:plain

問題一覧ページ

PG BATTLE 2019問題一覧

難易度1 Jump

問題

https://products.sint.co.jp/hubfs/resource/topsic/pgb/1-1.pdf

解法

境界判定をバグらせないように注意するだけ

fun main(args: Array<String>) {
    val (w, k, d) = readLine()!!.split(" ").map { it.toInt() }

    if(k <= d && w - k <= d) {
        println("Yes")
    } else {
        println("No")
    }
}

難易度2 AtCoder

問題

https://products.sint.co.jp/hubfs/resource/topsic/pgb/1-2.pdf

解法

文字列を全部小文字か大文字にそろえて比べることでMaybeの判定をする。

fun main(args: Array<String>) {
    val s = readLine()!!
    println(
        when {
            s == "AtCoder" -> "Yes"
            s.toLowerCase() == "atcoder" -> "Maybe"
            else -> "No"
        }
    )
}

上のコードでもいいのだが、実はString.equalsメソッドにはignoreCaseというオプションがあるので、それで大文字小文字の区別なく比較することができる。

fun main(args: Array<String>) {
    val s = readLine()!!
    println(
        when {
            s == "AtCoder" -> "Yes"
            s.equals("AtCoder", ignoreCase = true) -> "Maybe"
            else -> "No"
        }
    )
}

難易度3

問題

https://products.sint.co.jp/hubfs/resource/topsic/pgb/1-3.pdf

解法

変な風に解いてしまった。 ピンm本が立っているか倒れているかの配列を作り、シュミレーションするだけ。

j回目に投げる人はレーンjで投げて、開始からa+b秒後にボールがレーンに通達する。 倒れるピンの番号は、ピン番号+経過時間 = レーン番号より求まる。 後は倒れるピンの番号が1-mの間にあれば、配列を更新すればよい。

最後に配列を見て、倒れている個数をカウントする。

fun main(args: Array<String>) {
    val (n, m) = readLine()!!.split(" ").map { it.toInt() }
    val isPinArrive = BooleanArray(m) { true }
    for (j in 1..n) {
        val (a, b) = readLine()!!.split(" ").map { it.toInt() }
        val reachTime = a + b
        val lane = j
        val pinNumber = lane - reachTime
        if(pinNumber in 1..m) {
            isPinArrive[pinNumber - 1] = false
        }
    }
    println(isPinArrive.count { !it })
}

難易度4

問題

https://products.sint.co.jp/hubfs/resource/topsic/pgb/1-4.pdf

解法

各都市で暇をつぶすのは無限時間できる。 すると、各都市に対してできるだけ早く着いた方が選択支が増えるので嬉しいということがわかる。

また、ある都市を出てからもう一度同じ都市に回ってくるということはありえないこともわかる。それをするなら、その都市で同じ時間暇をつぶして待機すればいいだけだからである。

各都市に対して一番早く着く時間を求めるのはダイクストラ法でできるのだが、辺のコストを算出する処理がちょっとめんどくさい。 通る辺が通れない場合も考える必要がある。

コードはこちら、書いてるとき自分でも頭が混乱したのでコメントモリモリになってる。 答えがIntの範囲を越えそうだったのでLongを使ってる。

大きな流れとしては、まず隣接リストの構築をする。次にダイクストラ法で更新をしていく。最後に出力。 ダイクストラ法での更新時の、コスト算出が複雑なのでcalcCost関数に切り出した。

import java.util.*
import kotlin.comparisons.compareBy

const val INF = Long.MAX_VALUE / 2

fun main(args: Array<String>) {
    val (n, m, t, k) = readLine()!!
        .split(" ")
        .map { it.toInt() }
    //隣接リスト
    val edges = Array(n) {
        ArrayList<Edge>()
    }
    //隣接リストを構築
    repeat(m) {
        val (a, b, c, d) = readLine()!!
            .split(" ")
            .map { it.toLong() }
        edges[a.toInt() - 1].add(Edge((b - 1).toInt(), c, d))
        edges[b.toInt() - 1].add(Edge((a - 1).toInt(), c, d))
    }
    //(dijkstra中は推定値)最短時間
    val dist = LongArray(n)

    //fromReachTimeで頂点に到着し、そこからedgeを通る場合、一番早く渡れる時間を計算する
    fun calcCost(fromReachTime: Long, toEdge: Edge): Long {
        val moveCost = toEdge.cost
        val di = toEdge.di
        //いつでも通れる場合、すぐ通る
        if (di <= k) {
            return fromReachTime + moveCost
        }
        //tからどれだけ離れればギリギリ通れるか
        val outTime = di - k
        //混んで通れなくなる前に通る場合、一番遅い出発時間
        val leftLatest = t - outTime - moveCost
        //混んで通れなくなった後、一番最初に通れる時間
        val rightFastest = t + outTime

        return if (fromReachTime <= leftLatest) {
            fromReachTime + moveCost
        } else {
            Math.max(rightFastest, fromReachTime) + moveCost
        }
    }

    //start: 開始頂点
    //O(M log N)
    fun dijkstra(start: Int) {
        //distを初期化
        Arrays.fill(dist, INF)
        dist[start] = 0
        //キュー初期化
        val candidateQueue = PriorityQueue<Candidate>(1, compareBy { it.time })
        candidateQueue.add(Candidate(0, start))
        //最小値更新開始
        while (candidateQueue.isNotEmpty()) {
            val (c_time, c_v) = candidateQueue.poll()
            //意味のない情報を捨てる
            if (dist[c_v] < c_time) {
                continue
            }

            val toEdges = edges[c_v]
            for (e in toEdges) {
                val cost = calcCost(c_time, e)
                if (dist[e.to] > cost) {
                    dist[e.to] = cost
                    candidateQueue.add(Candidate(dist[e.to], e.to))
                }
            }
        }
    }

    dijkstra(0)
    if (dist[n - 1] == INF) {
        println(-1)
    } else {
        println(dist[n - 1])
    }
}

data class Candidate(val time: Long, val nodeNum: Int)
data class Edge(val to: Int, val cost: Long, val di: Long)

KEYENCE Programming Contest 2019 A-C解説

A - Beginning

問題

A - Beginning

解説

並べ替えて1974にできるか判定するということは、順番は関係ないということなので、1,4,7,9が1つづつ含まれていればいいということになります。 それをそのまま実装してもいいですし、ソートして1,4,7,9になるかを判定するという実装でもいいかもしれません。

ソートを使う方のコード例です

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] arr = {sc.nextInt(), sc.nextInt(), sc.nextInt(), sc.nextInt()};
        Arrays.sort(arr);
        int[] ok = {1,4,7,9};
        System.out.println(Arrays.equals(arr, ok) ? "YES" : "NO");
    }
}

B - KEYENCE String

問題

B - KEYENCE String

解説

キーエンス型文字列の定義は、連続した部分文字列(空でも良い)を1度だけ取り除くことで keyenceになるかです。

この定義から、Sがキーエンス型文字列の時、Sがどんな状態かは3通りあります。

  1. 先頭がkeyence
  2. 末尾がkeyence
  3. 先頭がkeyenceを前半と後半に分けた前半で、末尾が後半

最後のはわかりにくいと思います。例を出すと、keyenceをkeyとenceにわけたとき、keyhogehogeenceがキーエンス型文字列という感じです。

これをどう実装するかというと、keyecneをfor文で回してk+eyence, ke+yence, key+....という風に切っていき、前半が先頭にあり、後半が末尾にあるかを判定すればいいです。

コード例です。 substringメソッドでok("keyence")を切断して、startWithとendWithメソッドで判定しています。 先頭がkeyecne、末尾がkeyenceの場合はそれぞれ、 keyence+"", ""+keyenceという切り方ともいえるので、キーエンス型文字列の全パターンが列挙できています。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String ok = "keyence";
        String s = sc.next();
        for (int i = 0; i < ok.length(); i++) {
            if(s.startsWith(ok.substring(0,i)) && s.endsWith(ok.substring(i))) {
                System.out.println("YES");
                return;
            }
        }
        System.out.println("NO");
    }
}

C - Exam and Wizard

問題

C - Exam and Wizard

解説

総和が同じにならないといけないということから、準備が足りない試験に準備が足りている試験から、その余った分を配るという問題です。そして、変更した場所ができるだけ少なくないといけません。これを考えていきます。

  • 準備時間も必要な時間もちょうどの試験の場合(a[i]==b[i])、なにも変更する必要はありません。変更回数に影響がありません。
  • 準備が足りない試験(a[i] < b[i])は必ず変更しなければいけません。配られる側は必ず変更されます。
  • 準備が足りて、余りある試験(a[i] > b[i])は、準備が足りていない試験があるなら余った準備時間(a[i] - b[i])を配ります。配る側は配らない場合もあるので、変更しない場合もあります。

変更回数を減らすには、最後の、余った分を配る側をできるだけ少なくすればいいということになります。 すると、沢山余っている試験から順番に足りない部分に余った分を配ればいいということがわかるので、実装します。

実装上の注意

配られる側は、必ず変更されるので、全部でどれだけ足りていないかがわかればよく、個別にどれだけ足りないかはいりません。

配る側は、変更されるかわからないので、個別にどれだけ配れるかをlistで持っておく必要があります。

コード例

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //input
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        int[] b = new int[n];
        for (int i = 0; i < n; i++) a[i] = sc.nextInt();
        for (int i = 0; i < n; i++) b[i] = sc.nextInt();

        //余っている準備時間を試験ごとにわけてソートしたもの
        PriorityQueue<Integer> surplus = new PriorityQueue<>(Comparator.reverseOrder());
        //変更回数
        int count = 0;
        long shortage = 0L;//不足している準備時間

        for (int i = 0; i < n; i++) {
            if (a[i] == b[i]) continue;//ちょうどの場合
            if (a[i] > b[i]) {//余っている場合
                surplus.add(a[i] - b[i]);
            } else {//足りない場合
                shortage += (b[i] - a[i]);
                count++;
            }
        }
        while (shortage > 0) {
            Integer i = surplus.poll();
            if (i == null) {//足りない部分があるのに、もう配るものが無い場合、無理
                System.out.println(-1);
                return;
            }
            shortage -= i;
            count++;
        }

        System.out.println(count);
    }
}

Java入門8

今日の目標

条件分岐の文について学ぶ

準備

Code, Compile & Run | CodeChefにアクセスして、JAVAを選びます。

条件分岐とは

もし~だったら、...をする、そうでなければ...。というのをプログラムで表現します。

多くの言語と同じで、Javaではif文を使います。

とりあえず書いてみよう

int x = 10;//ここを色々変えてみてください
if(x > 0) {
    System.out.println("more than 0");
}
System.out.println("finish!");

これが一番単純な形のif文で、ifの後に続ける括弧の中には式を書きます。 その式はboolean型に評価される必要があり、trueならif文のブロック内が実行され、falseなら実行されず飛ばされます。

if文の種類

if文にはelse節と言って、falseの場合のみ実行されるブロックを付けることもできます。

int x = 10;//ここを色々変えてみてください
if(x > 0) {
    System.out.println("more than 0");
} else {
    System.out.println("0 or less");
}
System.out.println("finish!");

さらに複雑なif文

if文にはさらに、if節とelse節の間にelse-if節を好きなだけ作ることもできます。 else節はなくても構いません。

int x = 10;
if(x > 100) {
    System.out.println("more than 100");
} else if(x > 10) {
    System.out.println("more than 10");
} else if(x > 0) {
    System.out.println("more than 0");
} else {
    System.out.println("0 or less");
}

もし、xが100だとしたら、x > 100, x > 10, x > 0全てでtrueを返すので3つのブロックが実行されると思うかもしれません。 しかし、実際は上から評価して、一番最初にtrueを返したブロックを実行してif文を抜けます。

そのため、下のようなコードは意味がありません。

int x = 10;
if(x > 0) {
    System.out.println("more than 0");
} else if(x > 10) {
    //ここは絶対に実行されない
    System.out.println("more than 10")
}

x > 10がtrueを返すコードは必ずx > 0でもtrueを返します。 一番最初にtrueを返すブロックを実行するため、x > 10のブロックが実行されることはありません。

他の条件分岐文

if文の他に、switch-case文という条件分岐の文もあります。 気になる人は調べてみてください。ここでは省略します。 そこまで便利ではなく、記述が冗長で、バグが潜む危険が高い文のため、使われることはあまりありません。

if文のまとめ

if文は1つのif節と0個以上のif-else節と最後に0個か1個のelse節で構成される

最初にtrueを返したブロックが実行され、その後if文を抜ける。

演習

2つの数字のうち、大きい方を出力するプログラムの作成。

数字が0~100の間にあるか判定するプログラムの作成。

文字がa ~ zの間の文字か判定するプログラムの作成。

Java入門7

リテラル

リテラルとは、ソースコード中に埋め込んで意味を成すもののことです。

"abcd"123453.14trueなどがそうです。

文字列リテラル、整数リテラル、少数リテラルなどリテラルの種類で言い分けたりもします。

sjc-p.obx21.com

このリンクには、様々なリテラルが紹介されているので目を通してください。

逆にリテラルでないものとは、変数名、クラス名、関数名、などです。

例えばint a = 10;というコードがあったとして、aという変数名は別にbなどに変えても(使っている場所を全て変更すれば)ソースコードの意味は変わりません。 ソースコード中に埋め込まれたデータではないのでリテラルではありません。 しかし、10という数字は、これが11や20になるとソースコードの意味が全く異なります。これはデータなのでリテラルです。

基本型の変数に代入できるもの

基本型の変数に代入できるものは何でしょうか? 前の記事では型名 変数名 = 値と書きました。 しかしそれでは下のコードが動く説明ができません。

int a = 10;
int b = a + 20;

「a+20」は値ではないですよね?

正解を言うと、右辺にくるのは値ではなく、評価されてその型の値になる式です。

式とは、演算子オペランドと式を演算子の規則に従い並べたものです。 こう書くと難しく感じるかもしれませんが、例えば1 + 13 * xなどです。

式は式の一部になります

新しく出てきた用語達はこれから説明します。

演算子

演算子とは、Javaで決められている計算などを定義する記号のことで、それなりの種類があります。 全て覚える必要はありません。

java-code.jp

このリンクに種類についてよくまとまっています。

演算子はその演算子によりますが、1~3個のオペランドと呼ばれる計算対象をとります。 例えば、+演算子a + bのように、左と右にオペランドを取ります。 他には、=演算子で、a = bのように使い、aにbを代入します。 インクリメント演算子a++のように、1つしかオペランドをとらない演算子もあります。

演算子も式の構成要素です。

演算子には優先順位結合規則があります。 このコードを実行してみてください。 何が表示されるでしょうか。

class Codechef
{
    public static void main (String[] args) throws java.lang.Exception
    {
        int a = 10 + 5 * 3;
        int b = 5 * 3 + 10;
        System.out.println(a);
        System.out.println(b);
    }
}

この結果から、どの順番で書いたかに関わらず、加算より乗算が先に実行されることがわかります。 全ての演算子について、この優先順位が決まっています。 例えば、乗算*と加算+では乗算の方が優先順位が上です。

加算+と減算-では、同じ優先順位です。同じ優先順位の時は結合規則を考えます。 加算、減算は左結合の演算子なので、左から計算されます。

演算子オペランドと共に評価されるときの順番も、結合規則を考えます。 a + b+が左結合なので先にaを計算してからbを計算して、a+bの値を返します。

ちなみにですが、括弧で括ることにより、優先順位が一番高くなるので、複雑な式を書く場合は括弧を使って計算順序をわかりやすくするべきです。

評価

評価とは、誤解を恐れずに言えば計算することです。 今までの文の計算する、の部分は全部評価と言い換えて大丈夫です。 このようなコードがあり、今からJVMが下の行のコードを評価するとします。

int x = 10;
int y = (5 * 3) + x / 5;

まず、括弧内が一番優先順位が高いので、5*3が評価され、15という値を得ます。 この時点ではint y = 15 + x / 5;となっています。 次に、/演算子の優先順位が高いので、x / 5を実行します。 xは評価されて10になり、10 / 5で2という値を得ます。 そして次に優先順位が高い+を含む式を評価するので15 + 2が計算され、17という値が求まりました。 あとはint y = 17を評価すれば終わりです。こうしてyに17が代入されました。

すごく長かったですが、お疲れ様でした!

まとめ

AGC030-A解説

A - Poisonous Cookies

問題

A - Poisonous Cookies

解説

解毒できる美味しいクッキーは常に全て食べる。毒の美味しいクッキーをどれだけ食べられるかがミソになってくる。

毒の数 <= 解毒の数のときは言うまでもなく、毒の美味しいクッキーを全て食べられる。

毒の数 > 解毒の数の場合、毒の美味しいクッキーは解毒の数+1食べられる。

実装上の注意

int型は2 * 109程度しか入らない。今回はa,b,cの上限が109。 それらを足したりするのでオーバーフローに注意して、long型を使う。

ACコード

import java.util.Scanner;
 
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long a = sc.nextInt(), b = sc.nextInt(), c = sc.nextInt();
        if(c <= a+b) {
            System.out.println(b+c);
        } else {
            System.out.println(a+b+b+1);
        }
    }
}

Java入門6.5

はじめに

この記事はNITAC情研競プロ班の活動メモです。

Java入門1~6の内容をやった後の補足説明として僕が喋ったもののまとめになります。

Java入門3の補足

言語にはJavaのようにコンパイルしてから実行するコンパイラ言語と、コンパイルをせずに実行するスクリプト言語がある。

Javaは記事の通りコンパイラ言語。ソースコードの拡張子は.javaコンパイル結果はJavaバイトコードで、拡張子は.class

C++やCもコンパイル言語。ソースコードの拡張子はそれぞれ.cpp.cコンパイルすると実行形式ファイル.exeなどになる。

一方でスクリプト言語の例としては、pythonrubyなどがある。それぞれソースコードの拡張子は.py.rb

コンパイラ言語とスクリプト言語の違い

コンパイラ言語の特徴として、実行が早い、記述が冗長など。

スクリプト言語の特徴として、簡単に書ける。実行は比較的遅い。

一概にどちらが優れているとは言えず、ケースバイケースといったところです。

最近はスクリプト言語コンパイルしたりコンパイラ言語をスクリプトのように実行することも普通にできるようになってきていて、違いを意識することはないですが。

参考リンク:https://www.gwtcenter.com/what-is-scripting-language

Java入門4の補足

public static void main (String[] args) throws java.lang.Exception {

}

throws java.lang.Exceptionの部分はエラー処理のコードなので通常はいらない。消しても大丈夫。

public static void main(String[] args) {}について、今の知識だけで簡単に説明する。これは後の回でしっかり説明するので、こういう意味があるんだなー程度でいいです。

まず、このmainがあるプログラムは、起動して一番最初に呼ばれるプログラム。その一番最初に呼ばれるプログラムに何が求められるかというと

  • どこからでも呼び出せるようにオープンに
  • 最初に呼び出されるので、最初から存在している必要がある
  • 決まった名前の関数(最初に呼ばれるのは特別な名前)
  • 起動引数(プログラムのオプション)を受け取れる必要がある

よってpublic = オープンに、static = 最初から存在、void = 処理結果は返さない(最初に呼ばれるので返す場所がない)、main = 特別な名前、最初に実行される決まり、(String[] args) = 起動引数を取るため

となっている。よってpublic static void main(String[] args) {}

Java入門5,6の補足

byte型は1byte、shortは2byte、intは4byte、longは8byte。 何故1,2,3,4...ではなく20,21,22,23...となっているのか?

それはコンピューターが扱うのは2進数なので、2の乗数の大きさのメモリを使うほうが都合がよいから。

32bitコンピュータ、64bitコンピュータ

windowsなら、左下のwindowsマークを右クリックしてシステムという欄を開いてみよう。システムの種類のところに64ビットオペレーティングシステムなどと書いてあるはずだ。 これは「このコンピュータは64bitをひとかたまりとして計算したりしますよ」ということだ。

今の時代、ほぼ全てのコンピュータが64bitで、古いパソコンは32bitの場合もある。といったところだ。

整数型

上記の通り、32bitのint型か64bitのlong型がコンピュータにとって丁度良いのだが、int型とlong型のどちらを使えばいいのだろうか。 演算速度は変わらないので、プラスマイナス約21億(231)に収まる数しか格納しないのであれば、メモリ効率の良いint型を使うべきである。

浮動小数点型

floatとdoubleがあり、それぞれ4byteと8byteである。上のintとlongの話のように、4byteであるfloatを使えばいいのだろうか?否だ。doubleを使うべきである。

何故なら、intの1とlongの1はどちらも変わらず1を表す。しかし浮動小数点型においては違うからだ。

単純な話に置き換えてわかりやすく説明すると、floatでの1は1.00だとすると、doubleでの1は1.000000みたいなものである(実際は1はどちらでも誤差なく表すことができるが、説明の為省略)。有効数字(精度)が違うので、浮動小数点型を使う際はできるだけ精度のよいdouble型をつかうべきなのだ。

char型

char型は一文字を表す。実は内部に入っているのは数字である。コンピュータは65番の文字='A'、66番='B'のように、文字と数字を対応づけている。これの対応させる体系を文字コードという。 UTF-8SJISなどは聞いたこともあると思う。

コンピュータが65という数字を見た時、それを文字だ!と思って'A'と解釈するか、数字だ!と思って65と解釈するかは型が決める。型はデータの種類を表すというのはこういうことなのだ。

boolean型

intが-1,0,1,50などを持つのと比較すると、boolean型は2種類の値のどちらかしか持てない。具体的にいうと、true(ホント)とfalse(ウソ)の2種類を持つ。 これらは後に勉強する条件分岐の文などで使われる。

String型は基本型なのか

これはJava初心者が間違えやすい注意ポイントなのだが、String型は参照型である。少しだけJavaに特別扱いされているので間違えやすいが、これは後々も使う大事な知識なので間違えずに覚えること。

Java入門6

今日の目標

基本型について知る

基本型について学ぼう

www.okapiproject.com

によくまとまっているので、目を通してください。

以下、補足

基本型はプリミティブ型とも呼ばれる。

整数型について

byte、short、int、longと整数型には沢山の種類があります。 これらの本質的な違いは使用するメモリの量です。沢山のメモリを使えば使うほど、大きな数も扱えるようになります

byte型、short型はメモリが潤沢にない時代には使われていたこともあったようですが、メモリが大容量化した今の時代にあえてbyte型、short型を使う人はいません基本的に整数を扱うときはint型を使いましょう

int型で表すことのできる範囲(だいたい±21億、±109)を超えるような数字を扱うときのみ、longを使うようにしましょう。

浮動小数点型について

浮動小数点とは何でしょうか?これは、少数を内部でどう表しているかを示しています。詳しく知りたい人は検索してみてください。

こちらも、メモリを節約するためにfloat型を使う時代もありましたが、今はできるだけ高精度なdouble型を使うようにしましょう。float型は基本的に使いません。

文字型について

char型のみです。””文字””型なので一文字しか表現できません。 実は、"Hello, World!"などの文字列はchar型を沢山集めて表現しています。

ブール型

真偽値型、ブーリアンなど様々な呼び方があります。

これは2通りの状態(true:真かfalse:偽)しか持ちません。次回以降にする条件分岐の条件に使われます。

実践してみる

さて、これで皆さんは変数の宣言、およびプリミティブ型について学習しました。これらを使ったプログラムを書いて見ましょう。

準備

Code, Compile & Run | CodeChefにアクセスして、JAVAを選びます。

class Codechef
{
    public static void main (String[] args)
    {
        int i = -21000000;
        int i2 = 30352534;
        int i3 = i + i2;
        long l = 535252523853205L;
        double d = 3.1415924324325555555;
        char c = 'A';
        boolean b = true;
        boolean b2 = false;
        boolean b3 = 3 > 2;
        
        System.out.println(d);
        System.out.println(b3);
        
        double result = 1000 * d;
        System.out.println(result);
    }
}

int i3 = i + i2;では、右辺は値ではなく、別の変数を含む計算式の結果になっています。これも変数に代入できます。

long型の値の末尾には大文字のLを付けることに注意してください。つけない場合、int型の値と解釈され、21億を超えているのでコンパイルエラーになります。

まだ、double型に入れた実際の値3.1415924324325555555と、出力結果の値3.1415924324325557が違うことに注目してください。 double型の精度の限界です。

また、3 > 2の結果をboolean型の変数に代入できていることにも注目してください。 代入できるということは、3 > 2はboolean型の値を返すということがわかります。

double result = 1000 * d;ここでは、int型の値1000とdouble型の値を掛けています。 その結果はintなのでしょうか?それともdoubleなのでしょうか?。 見ればわかる通り、double型になります。

次回は変数に代入しているのが何なのかについて詳しくやります。