0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Goで学ぶコンピューターサイエンスAdvent Calendar 2024

Day 2

【Goで学ぶコンピューターサイエンス】進数とエンコーディング

Last updated at Posted at 2024-12-03

進数

進数とは、数を表現する方法です。
日常的に使っている「10進数」もその一つですが、コンピュータでは特に以下の進数がよく使われます。

2進数(Binary)

  • 基数:2
  • 使用する数字:0, 1
  • コンピュータの最も基本的な数値表現。ビット(0または1)を用いる

8進数(Octal)

  • 基数:8
  • 使用する数字:0〜7
  • Linuxのパーミッション管理で使われている

16進数(Hexadecimal)

  • 基数:16
  • 使用する数字:0〜9、A〜F(10進数の10〜15を表す)
  • 大量の2進数を短く表現するために便利。メモリのアドレス指定やカラーコードで使われている

エンコーディング

エンコーディングとは、データを特定のルールに基づいて符号化することです。

文字エンコーディング

  • ASCII:
    • 7ビットで英数字や記号を表現
    • 例:「A」は10進数で65、2進数で01000001
  • UTF-8:
    • 可変長のエンコーディング
    • ASCIIと互換性があり、世界中の文字を表現可能

データエンコーディング

  • Base64:
    • バイナリデータをテキスト形式に変換
    • メールやURLでバイナリデータを扱う際に便利
  • URLエンコーディング:
    • 特殊文字を % と16進数で表現します。Webで安全にデータを転送するために使用

進数のGoサンプルコード

10進数から他の進数への変換

package main

import "fmt"

func main() {
    decimal := 255

    fmt.Printf("Decimal: %d\n", decimal)
    fmt.Printf("Binary: %b\n", decimal)   // 2進数
    fmt.Printf("Octal: %o\n", decimal)    // 8進数
    fmt.Printf("Hexadecimal: %X\n", decimal) // 16進数
}
Decimal: 255
Binary: 11111111
Octal: 377
Hexadecimal: FF

進数を10進数に変換

package main

import (
	"fmt"
	"strconv"
)

func main() {
	binary := "11111111" // 2進数
	octal := "377"       // 8進数
	hex := "FF"          // 16進数

	// 2進数→10進数
	decimalBinary, _ := strconv.ParseInt(binary, 2, 64)
	fmt.Printf("Binary to Decimal: %d\n", decimalBinary)

	// 8進数→10進数
	decimalOctal, _ := strconv.ParseInt(octal, 8, 64)
	fmt.Printf("Octal to Decimal: %d\n", decimalOctal)

	// 16進数→10進数
	decimalHex, _ := strconv.ParseInt(hex, 16, 64)
	fmt.Printf("Hexadecimal to Decimal: %d\n", decimalHex)
}
Binary to Decimal: 255
Octal to Decimal: 255
Hexadecimal to Decimal: 255

エンコーディングのGoサンプルコード

文字列をバイトに変換(UTF-8)

package main

import "fmt"

func main() {
	text := "こんにちは🌏" // 日本語と地球の絵文字を含む文字列
	bytes := []byte(text)

	fmt.Printf("Text: %s\n", text)
	fmt.Printf("Bytes: %v\n", bytes)

	fmt.Println("\nDetails of each byte (UTF-8 encoding):")
	// 各バイトを2進数で表示
	for i, b := range bytes {
		fmt.Printf("Byte %d: %08b\n", i, b)
	}

	fmt.Println("\nCharacter-wise breakdown:")
	// 各文字のUTF-8エンコーディングを表示
	for i, r := range text {
		fmt.Printf("Character %d: '%c' (code point: %U)\n", i, r, r)
	}
}

UTF-8だと、ひらがなは3バイト、絵文字は4バイトなのが確認できる

Text: こんにちは🌏
Bytes: [227 129 147 227 130 147 227 129 171 227 129 161 227 129 175 240 159 140 143]

Details of each byte:
Byte 0: 11100011
Byte 1: 10000001
Byte 2: 10010011
Byte 3: 11100011
Byte 4: 10000010
Byte 5: 10010011
Byte 6: 11100011
Byte 7: 10000001
Byte 8: 10101011
Byte 9: 11100011
Byte 10: 10000001
Byte 11: 10100001
Byte 12: 11100011
Byte 13: 10000001
Byte 14: 10101111
Byte 15: 11110000
Byte 16: 10011111
Byte 17: 10001100
Byte 18: 10001111

Character-wise breakdown:
Character 0: 'こ' (code point: U+3053)
Character 3: 'ん' (code point: U+3093)
Character 6: 'に' (code point: U+306B)
Character 9: 'ち' (code point: U+3061)
Character 12: 'は' (code point: U+306F)
Character 15: '🌏' (code point: U+1F30F)

Base64エンコーディング

package main

import (
	"encoding/base64"
	"fmt"
	"os"
)

func main() {
	// 画像を読み込む
	filePath := "example.png"
	binaryData, err := os.ReadFile(filePath)
	if err != nil {
		fmt.Println("ファイルの読み込みに失敗しました:", err)
		return
	}

	fmt.Println("元のバイナリデータの長さ:", len(binaryData), "バイト")

	// Base64エンコード
	base64Encoded := base64.StdEncoding.EncodeToString(binaryData)
	fmt.Println("Base64エンコード後のデータ:")
	fmt.Println(base64Encoded[:100], "続く...") // データの一部を表示

	// Base64デコード
	decodedData, err := base64.StdEncoding.DecodeString(base64Encoded)
	if err != nil {
		fmt.Println("Base64デコードに失敗しました:", err)
		return
	}

	fmt.Println("デコード後のバイナリデータの長さ:", len(decodedData), "バイト")

	// デコードしたデータを新しいファイルとして保存
	outputPath := "decoded_example.png"
	err = os.WriteFile(outputPath, decodedData, 0644)
	if err != nil {
		fmt.Println("デコードしたデータの書き込みに失敗しました:", err)
		return
	}

	fmt.Println("デコードしたデータをファイルとして保存しました:", outputPath)
}
元のバイナリデータの長さ: 46710 バイト
Base64エンコード後のデータ:
iVBORw0KGgoAAAANSUhEUgAAAZAAAAH0CAMAAAAkBIuyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhp 続く...
デコード後のバイナリデータの長さ: 46710 バイト
デコードしたデータをファイルとして保存しました: decoded_example.png

URLエンコーディング

package main

import (
	"fmt"
	"net/url"
)

func main() {
	// サンプルデータ:エンコードする文字列
	rawString := "こんにちは! 😊 & Go=楽しい"

	// URLエンコーディング
	encoded := url.QueryEscape(rawString)
	fmt.Println("エンコード結果:", encoded)

	// エンコードされた文字列をデコード
	decoded, err := url.QueryUnescape(encoded)
	if err != nil {
		fmt.Println("デコードエラー:", err)
		return
	}
	fmt.Println("デコード結果:", decoded)

	// URLにクエリパラメータとして追加
	baseURL := "https://example.com/search"
	params := url.Values{}
	params.Add("query", rawString)
	fullURL := fmt.Sprintf("%s?%s", baseURL, params.Encode())
	fmt.Println("クエリ付きURL:", fullURL)

	// クエリパラメータを解析
	parsedURL, err := url.Parse(fullURL)
	if err != nil {
		fmt.Println("URL解析エラー:", err)
		return
	}
	queryParams := parsedURL.Query()
	fmt.Println("解析されたクエリパラメータ:", queryParams.Get("query"))
}
エンコード結果: %E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%21+%F0%9F%98%8A+%26+Go%3D%E6%A5%BD%E3%81%97%E3%81%84
デコード結果: こんにちは! 😊 & Go=楽しい
クエリ付きURL: https://example.com/search?query=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%21+%F0%9F%98%8A+%26+Go%3D%E6%A5%BD%E3%81%97%E3%81%84
解析されたクエリパラメータ: こんにちは! 😊 & Go=楽しい
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?