評価3: 基本構文と変数の理解 - 評価基準

評価の目的

この評価では、学生がZigの基本的な構文、型システム、演算子を理解し、実用的なプログラムを作成できるかを確認します。型の正確な理解は、Zigプログラミングの基礎となる重要なスキルです。

学習目標

  • Zigのプリミティブ型(整数、浮動小数点、ブール、文字)を理解し使用できる
  • 型変換を安全に実装できる
  • 各種演算子(算術、ビット、比較、オーバーフロー対策)を適切に使用できる
  • 実用的なプログラム(温度変換など)を実装できる
  • 任意ビット幅整数やcomptime型推論などの高度な機能を理解できる

評価項目

1. 型の理解(25点)

項目 配点 評価基準
**整数型の使用** 10点 10点:符号付き/符号なし整数の各サイズ(i8,i16,i32,i64,u8,u16,u32,u64)を正しく使用し、最大値・最小値を表示
7点:主要な型は使用できるが、一部不正確
4点:基本的な型のみ使用
0点:理解が不十分
**浮動小数点型** 5点 5点:f32とf64の違いを理解し、精度の違いを示せる
3点:使用できるが精度の違いの理解が浅い
0点:適切に使用できない
**ブール・文字型** 5点 5点:ブール値と論理演算、ASCII/Unicode文字を正しく扱える
3点:基本的な使用のみ
0点:使用できない
**出力フォーマット** 5点 5点:適切なフォーマット指定子を使用し、読みやすい出力
3点:出力はされるがフォーマットが不適切
0点:フォーマットの理解なし

実装チェックポイント:

// 整数型の最大値・最小値
const i8_min = std.math.minInt(i8);   // -128
const i8_max = std.math.maxInt(i8);   // 127
const u8_max = std.math.maxInt(u8);   // 255

// 浮動小数点の精度
const pi_f32: f32 = 3.14159265;
const pi_f64: f64 = 3.14159265358979;

// フォーマット指定子
std.debug.print("{}\n", .{整数});      // 整数
std.debug.print("{d:.2}\n", .{浮動});  // 小数点2桁
std.debug.print("{s}\n", .{文字列});   // 文字列

2. 型変換(25点)

項目 配点 評価基準
**基本的な型変換** 10点 10点:intToFloat、floatToIntが正しく動作し、適切な型キャストを使用
7点:動作するが型キャストの理解が不十分
3点:部分的に動作
0点:動作しない
**拡張・縮小変換** 10点 10点:widenIntとnarrowIntの両方を正しく実装し、範囲チェックを含む
7点:基本的な変換はできるが、エラー処理が不十分
3点:拡張のみまたは縮小のみ
0点:動作しない
**エラー処理** 5点 5点:narrowIntで範囲外の値を適切にエラーとして処理
3点:エラー処理はあるが不完全
0点:エラー処理なし

評価ポイント:

// 正しい型変換の例
fn intToFloat(value: i32) f64 {
    return @floatFromInt(value);
}

fn floatToInt(value: f64) i32 {
    return @intFromFloat(value);
}

fn narrowInt(value: i32) !i16 {
    if (value < std.math.minInt(i16) or value > std.math.maxInt(i16)) {
        return error.Overflow;
    }
    return @intCast(value);
}

3. 演算子の活用(25点)

項目 配点 評価基準
**算術演算** 7点 7点:加減乗除余が正しく実装され、適切に表示される
5点:基本演算はできるが、一部不正確
2点:限定的な実装
0点:動作しない
**ビット演算** 8点 8点:AND、OR、XOR、NOT、シフト演算すべてを正しく実装
6点:主要なビット演算を実装
3点:一部のビット演算のみ
0点:理解が不十分
**比較演算** 5点 5点:すべての比較演算子(<, >, <=, >=, ==, !=)を使用
3点:基本的な比較のみ
0点:不適切
**オーバーフロー対策** 5点 5点:ラップアラウンド(+%=)と飽和演算(+\ =)の違いを理解し実装
3点:使用できるが説明が不十分
0点:理解していない

実装例:

// オーバーフロー対策の演算
var x: u8 = 255;
x +%= 1;  // ラップアラウンド: 255 + 1 = 0
std.debug.print("Wrapping: {}\n", .{x});

var y: u8 = 255;
y +|= 1;  // 飽和演算: 255 + 1 = 255 (最大値で飽和)
std.debug.print("Saturating: {}\n", .{y});

4. 実践プログラム(25点)

項目 配点 評価基準
**変換関数の実装** 12点 12点:4つの変換関数すべてが正しい計算式で実装されている
9点:3つの関数が正しい
6点:2つの関数が正しい
0点:1つ以下
**CLI処理** 8点 8点:引数解析、単位判定、適切なエラーメッセージを実装
6点:基本的な処理はできるが、エラー処理が不十分
3点:限定的な機能
0点:動作しない
**出力品質** 5点 5点:適切な小数点精度と単位記号を含む読みやすい出力
3点:出力はあるが品質が低い
0点:不適切

温度変換の正しい式:

// 摂氏から華氏: F = C × 9/5 + 32
fn celsiusToFahrenheit(celsius: f64) f64 {
    return celsius * 9.0 / 5.0 + 32.0;
}

// 華氏から摂氏: C = (F - 32) × 5/9
fn fahrenheitToCelsius(fahrenheit: f64) f64 {
    return (fahrenheit - 32.0) * 5.0 / 9.0;
}

// 摂氏からケルビン: K = C + 273.15
fn celsiusToKelvin(celsius: f64) f64 {
    return celsius + 273.15;
}

// ケルビンから摂氏: C = K - 273.15
fn kelvinToCelsius(kelvin: f64) f64 {
    return kelvin - 273.15;
}

ボーナス課題の評価

Bonus 1: 任意ビット幅整数(15点)

配点 評価基準
15点 さまざまなビット幅(i3,u5,u7など)を正しく使用し、範囲と用途を説明
10点 任意ビット幅整数を使用できるが、説明が不十分
5点 限定的な使用のみ
0点 理解が不十分

評価ポイント:

  • i3: -4 から 3 までの4ビット符号付き整数
  • u5: 0 から 31 までの5ビット符号なし整数
  • ビットフラグとしての活用例
  • メモリ効率の理解

Bonus 2: comptime型推論(15点)

配点 評価基準
15点 `@typeInfo`を使用し、符号付き/符号なし両方の最大値・最小値を計算
10点 基本的な型情報取得はできるが、計算が不完全
5点 `@typeInfo`の使用のみ
0点 動作しない

実装例:

fn maxValue(comptime T: type) T {
    const info = @typeInfo(T);
    return switch (info) {
        .Int => |int_info| blk: {
            if (int_info.signedness == .unsigned) {
                break :blk (@as(T, 1) << int_info.bits) - 1;
            } else {
                break :blk (@as(T, 1) << (int_info.bits - 1)) - 1;
            }
        },
        else => @compileError("Unsupported type"),
    };
}

Bonus 3: ビット操作ユーティリティ(20点)

配点 評価基準
20点 6つの関数すべてが正しく動作し、適切なビット操作を実装
15点 4-5個の関数が正しく動作
10点 3個の関数が正しく動作
5点 1-2個のみ
0点 ほとんど動作しない

実装チェックポイント:

fn setBit(value: u32, bit: u5) u32 {
    return value | (@as(u32, 1) << bit);
}

fn clearBit(value: u32, bit: u5) u32 {
    return value & ~(@as(u32, 1) << bit);
}

fn toggleBit(value: u32, bit: u5) u32 {
    return value ^ (@as(u32, 1) << bit);
}

fn checkBit(value: u32, bit: u5) bool {
    return (value & (@as(u32, 1) << bit)) != 0;
}

fn countBits(value: u32) u6 {
    return @popCount(value);
}

fn reverseBytes(value: u32) u32 {
    return @byteSwap(value);
}

Bonus 4: 数値フォーマッター(20点)

配点 評価基準
20点 4つのフォーマット関数すべてが正しく動作し、適切な文字列を生成
15点 3個の関数が正しく動作
10点 2個の関数が正しく動作
5点 1個のみ
0点 ほとんど動作しない

実装ヒント:

  • std.fmt.allocPrintを使用した文字列生成
  • カンマ区切り: 1000000 → "1,000,000"
  • 人間が読みやすいサイズ: 1024 → "1 KB", 1048576 → "1 MB"

評価チェックリスト

マンダトリー要件

  • [ ] Part 1で全ての型を正しく使用している
  • [ ] Part 1で最大値・最小値を正確に表示している
  • [ ] Part 2の4つの型変換関数すべてが動作する
  • [ ] Part 2のnarrowIntで範囲チェックが実装されている
  • [ ] Part 3の算術、ビット、比較演算すべてが実装されている
  • [ ] Part 3のオーバーフロー対策演算が正しく動作する
  • [ ] Part 4の4つの温度変換関数が正しい計算式で実装されている
  • [ ] Part 4のCLIで引数解析とエラー処理が適切
  • [ ] すべてのコードがコンパイルエラーなく動作する
  • [ ] 提出物のディレクトリ構造が要件を満たす

コード品質

  • [ ] 変数名が意味を持っている
  • [ ] 適切なインデントとフォーマット
  • [ ] 型が明示的に指定されている
  • [ ] フォーマット指定子が適切
  • [ ] エラーメッセージがわかりやすい

ボーナス要件

  • [ ] Bonus 1: 複数の任意ビット幅整数を使用
  • [ ] Bonus 2: @typeInfoを使用した型情報取得
  • [ ] Bonus 2: maxValueとminValueの両方を実装
  • [ ] Bonus 3: 6つのビット操作関数すべてが動作
  • [ ] Bonus 4: 4つのフォーマット関数すべてが動作
  • [ ] Bonus 4: メモリリークがない(allocator.free使用)
  • 合格基準

    レベル 点数 説明
    **優秀** 90-100点 すべての型を正確に理解し、複雑な型変換やビット操作を実装できる。ボーナス課題で高度な機能を活用している。
    **良好** 80-89点 基本的な型システムを理解し、型変換と演算子を適切に使用できる。一部のボーナス課題に取り組んでいる。
    **合格** 70-79点 型の基礎を理解し、基本的なプログラムを作成できる。いくつかの改善点はあるが、次へ進める水準。
    **要再提出** 0-69点 型システムの理解が不十分、または実装に重大な問題。基礎の復習と再提出が必要。

    学習の手引き

    効果的な学習方法

  • 型システムの理解
- まずは基本的な整数型と浮動小数点型から始める - 各型の範囲を実際に出力して確認 - オーバーフロー動作を実験する

  • 型変換の練習
- 安全な型変換と危険な型変換の違いを理解 - エラー処理を含む変換関数を実装 - コンパイラエラーから学ぶ

  • 演算子の習得
- 各演算子を単独で試す - ビット演算を2進数表示で確認 - オーバーフロー対策演算の動作を確認

  • 実践的なプログラム作成
- 小さな機能から始める - テストケースを用意する - 段階的に機能を追加

よくある間違いと対策

間違い1: 型の不一致

// ❌ 間違い
const x: i32 = 10;
const y: f64 = x;  // コンパイルエラー

// ✅ 正しい
const x: i32 = 10;
const y: f64 = @floatFromInt(x);

間違い2: オーバーフロー

// ❌ 間違い(デバッグビルドでパニック)
var x: u8 = 255;
x += 1;

// ✅ 正しい(意図を明示)
var x: u8 = 255;
x +%= 1;  // ラップアラウンド
// または
x +|= 1;  // 飽和演算

間違い3: 型キャストの乱用

// ❌ 問題あり
fn narrowInt(value: i32) i16 {
    return @intCast(value);  // 範囲チェックなし
}

// ✅ 正しい
fn narrowInt(value: i32) !i16 {
    if (value < std.math.minInt(i16) or value > std.math.maxInt(i16)) {
        return error.Overflow;
    }
    return @intCast(value);
}

間違い4: ビット演算の優先順位

// ❌ 間違い(優先順位に注意)
const result = value & 1 << 3;

// ✅ 正しい
const result = value & (@as(u32, 1) << 3);

デバッグのヒント

  • 型エラーのデバッグ
- コンパイラのエラーメッセージを注意深く読む - 期待される型と実際の型を確認 - 必要に応じて明示的な型変換を追加

  • 計算結果の確認
- 中間値を出力して確認 - 2進数表示でビット演算を確認: {b:08} - 16進数表示: {x:08}

  • 範囲チェック
- std.math.minIntstd.math.maxIntで範囲確認 - テストケースに境界値を含める - エッジケースを意識する

学習リソース

  • 公式ドキュメント
- Zig Language Reference - Types: https://ziglang.org/documentation/master/#Types - Zig Language Reference - Operators: https://ziglang.org/documentation/master/#Operators

  • 標準ライブラリ
- std.math: https://ziglang.org/documentation/master/std/#std.math - std.fmt: https://ziglang.org/documentation/master/std/#std.fmt

  • コミュニティリソース
- Zig Learn - Chapter 1: https://ziglearn.org/chapter-1/ - Ziglings: https://github.com/ratfactor/ziglings

時間配分の目安

パート 推奨時間 内容
Part 1 2-3時間 型の理解と実装
Part 2 2-3時間 型変換関数の実装
Part 3 2-3時間 演算子の実装とテスト
Part 4 2-3時間 温度変換プログラム
Bonus 1 1-2時間 任意ビット幅整数
Bonus 2 2-3時間 comptime型推論
Bonus 3 3-4時間 ビット操作
Bonus 4 3-4時間 フォーマッター

合計: マンダトリーで8-12時間、ボーナス込みで17-25時間

評価後のフィードバック例

優秀な提出物の場合

型システムの理解が非常に優れています。特に、任意ビット幅整数の
活用とcomptime型推論の実装は、Zigの高度な機能を深く理解して
いることを示しています。

ビット操作ユーティリティの実装は効率的で、エッジケースも適切に
処理されています。フォーマッターの実装も読みやすく、メモリ管理も
完璧です。

次のステップ: ジェネリックプログラミングやメタプログラミングに
進むことをお勧めします。

改善が必要な場合

基本的な型の理解はできていますが、以下の点で改善が必要です:

1. 型変換でエラー処理が不十分です。narrowInt関数で範囲チェックを
   追加してください。
2. オーバーフロー対策演算の使い分けが理解できていません。
   ラップアラウンド(+%=)と飽和演算(+|=)の違いを確認してください。
3. ビット演算で括弧が不足し、意図しない結果になっています。

改善のヒント:
- エラー型を返す関数には必ず!を付ける
- ビット演算では常に括弧で優先順位を明示
- std.mathの関数を活用する

参考: Zig Language Reference の Types と Operators を復習してください。

参考資料

  • Zig Language Reference - Types: https://ziglang.org/documentation/master/#Types
  • Zig Language Reference - Operators: https://ziglang.org/documentation/master/#Operators
  • Zig Standard Library - math: https://ziglang.org/documentation/master/std/#std.math
  • Zig Standard Library - fmt: https://ziglang.org/documentation/master/std/#std.fmt
  • Zig Learn - Types: https://ziglearn.org/chapter-1/#types