C言語④(2025/05/14)

実数型

型名値の大まかな範囲サイズ
float-3.4×10^38~3.4×10^3832bit
double-1.7×10^308~1.7×10^30864bit

それぞれ
32ビット符号付浮動小数点数
64ビット符号付浮動小数点数
と呼ぶこともある。

数値の後にfをつけた小数はfloat型。fがない小数はdouble型として解釈される。
float rate = 0.23f;

【今日のコード①】

#include<stdio.h>

int main(void)
{
	int age1 = 45, age2 = 18;

	printf(" %d歳!でも%sは%d歳!!\n", age1,"心", age2);

	float weight = 83.7;
	printf("そして体重は%fkg!!", weight);

	return 0;
}

無理やりint型にfloatの数値を入れようとするとどうなるか・・・
ということを踏まえて
【今日のコード②】

#include<stdio.h>

int main(void)
{
	int age1 = 45, age2 = 18;
	int b = 2;

	printf(" %d歳!でも%sは%d歳!!\n", age1,"心", age2);

	float weight = 83.7;
	printf("そして体重は%fkg!!\n", weight);

	b = 0.2f;
	printf("面の皮の厚さは%fcm!! ",b);

	return 0;
}

<実行結果>

 45歳!でも心は18歳!!
そして体重は83.699997kg!!
面の皮の厚さは0.000000cm!!

bに代入しようとした小数点以下が切り捨てられ、0.00000に丸められている。
あと、weightには83.7を代入しているが、実際には83.699997になっている。
これは 浮動小数点数の誤差 が原因です! float 型は IEEE 754 規格に基づいて 約32ビットの精度 で値を保持しています。
しかし、コンピュータ内部では 2進数 で浮動小数点数を表すため、10進数の一部の値が 正確に表現できない のです。

例えば、83.7 は 10進数では正確な値ですが、2進数では 完全に一致する表現がない ため、内部で 近似値 として保持されます。
その結果、実際の printf の出力では わずかにズレる のです。

体重管理アプリのような 精度が求められるシステム では、浮動小数点の誤差を最小限に抑えるために、以下のような対策が取られています。

1. float の代わりに double を使用する

  • double64ビット の精度を持ち、float よりも誤差が少なくなります。
  • 例えば、体重を管理する場合:

double weight = 83.7; printf(“正確な体重は%.15f kg\n”, weight); %.15f のように桁数を調整すれば、より精度の高い表示が可能です。

2. 金額計算と同様に整数で扱う

  • floatdouble の代わりに 整数型(intlong)を使う 方法もあります。
  • 例えば、体重を 1000倍(g単位)にして整数で管理 すると、誤差の影響が減ります:

int weight_grams = (int)(weight * 1000); printf(“正確な体重は%d g\n”, weight_grams);

  • この方法は金融業界など お金の計算 にも使われています。(例えば、円単位ではなく銭単位で計算する)

3. 任意精度計算(多倍長演算)

  • BigDecimal(Java)Decimal(Python) などのライブラリを使い、精度を保証する。
  • 例えば、Python では decimal.Decimal を使うことで浮動小数点の誤差を防げます:

from decimal import Decimal weight = Decimal(‘83.7’) print(f”正確な体重は {weight} kg”)

  • Decimal 型は小数を 10進数として正確に管理 するため、誤差が出ない。

4. ユーザー向けの丸め処理

  • 表示時に 適切な桁数に丸める ことで、ユーザーに誤差を意識させない。
  • 例えば、printf("%.1f", weight) のように 小数第1位まで表示 すれば、違和感なく見える。

体重管理アプリなどでは、こうした方法を組み合わせて 誤差を防ぎつつ、計算のパフォーマンスを最適化 しています。
どの方法を選ぶかは、アプリの仕様やユーザー体験の優先度 によりますね!面白いテーマですね。

(by Copilot)

文字コード

コンピューターで文字を扱う際は、各文字に文字コード(数値)が割り当てられている為それを利用する。その文字コードの規格の一つがASCIIコードとなる。
記号、英数字、空白などを、0~127の番号に対応させている。
https://www3.nit.ac.jp/~tamura/ex2/ascii.html

上記を踏まえて
【今日のコード③】

#include<stdio.h>

int main(void)
{
	int age1 = 45, age2 = 18;
	int skin = 2;

	printf(" %d歳!でも%sは%d歳!!\n", age1,"心", age2);

	float weight = 83.7;
	printf("そして体重は%fkg!!\n", weight);

	skin = 0.2f;
	printf("面の皮の厚さは%fcm!!\n ",skin);

	char letter = 'A';
	printf("文字コード(10進数):%d\n", letter);
	printf("文字コード(16進数):0x%x\n", letter);
	printf("文字:%c\n", letter);

	return 0;
}
 45歳!でも心は18歳!!
そして体重は83.699997kg!!
面の皮の厚さは0.000000cm!!
 文字コード(10進数):65
文字コード(16進数):0x41
文字:A


文字列

文字列の最後には\0(NULL文字=メモリ上の数値としては”0”)が存在する。文字列の終了を意味する。表示はされない。コードで表現すると’\0’。
文字列は「変数」には代入できないので「配列」として取り扱う。
※配列について:https://9cguide.appspot.com/13-01.html

char string[10];
↑  ↑  ↑
型 配列名 要素数(変数の個数)

※要素数[10]とした場合に各要素を指定する場合には[0]~[9]までになる。
使いまわしをする場合、要素数はできるだけ多く確保する。[256]など。
なぜならば、例えば代入しようとした文字数が配列の上限数を超えると、確保したメモリ領域をオーバーしてほかのメモリを上書きし、ほかのデータに干渉してセキュリティや動作不良のもとになる。
(バッファオーバーフロー)

コメント

タイトルとURLをコピーしました