実数型
型名 | 値の大まかな範囲 | サイズ |
float | -3.4×10^38~3.4×10^38 | 32bit |
double | -1.7×10^308~1.7×10^308 | 64bit |
それぞれ
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
を使用する
double
は 64ビット の精度を持ち、float
よりも誤差が少なくなります。- 例えば、体重を管理する場合:
double weight = 83.7; printf(“正確な体重は%.15f kg\n”, weight); %.15f
のように桁数を調整すれば、より精度の高い表示が可能です。
2. 金額計算と同様に整数で扱う
float
やdouble
の代わりに 整数型(int
やlong
)を使う 方法もあります。- 例えば、体重を 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]など。
なぜならば、例えば代入しようとした文字数が配列の上限数を超えると、確保したメモリ領域をオーバーしてほかのメモリを上書きし、ほかのデータに干渉してセキュリティや動作不良のもとになる。
(バッファオーバーフロー)
コメント