float16和int16的表达实践
【摘要】 在完成了解析学习之后,我们来做个实践编程,代码如下:import numpy as npimport struct# int16 的范围int16_min = np.iinfo(np.int16).minint16_max = np.iinfo(np.int16).max# float16 的范围 float16_min = np.finfo(np.float16).minfloat16_...
在完成了解析学习之后,我们来做个实践编程,代码如下:
import numpy as np
import struct
# int16 的范围
int16_min = np.iinfo(np.int16).min
int16_max = np.iinfo(np.int16).max
# float16 的范围
float16_min = np.finfo(np.float16).min
float16_max = np.finfo(np.float16).max
float16_tiny = np.finfo(np.float16).tiny # 最小的正规化数
print("1. 数值范围对比:")
print(f"int16 范围: [{int16_min:,} 到 {int16_max:,}]")
print(f"float16范围: [{float16_min:.4e} 到 {float16_max:.4e}]")
print(f"float16最小正数: {float16_tiny:.4e}")
print(f"float16最大值 / int16最大值 ≈ {float16_max / int16_max:.4f} 倍")
def print_binary_representation(value, dtype, description):
"""打印任何数据类型的二进制表示"""
if dtype == np.int16:
data = np.array([value], dtype=dtype)
binary = format(data.view(np.uint16)[0], '016b')
else: # float16
data = np.array([value], dtype=dtype)
# 将float16转换为整数来查看位模式
binary = format(struct.unpack('<H', data.tobytes())[0], '016b')
print(f"{description:>20} ({value}): {binary}")
print("\n2. 二进制表示对比:")
print_binary_representation(1, np.int16, "int16 1")
print_binary_representation(1.0, np.float16, "float16 1.0")
print_binary_representation(-1, np.int16, "int16 -1")
print_binary_representation(-1.0, np.float16, "float16 -1.0")
print_binary_representation(-2, np.int16, "int16 -2")
print_binary_representation(-32768, np.int16, "int16 -32768")
print("\n3. float16 精度实验 - 体验'不均匀刻度':")
# 在小数区域的精度
small_number = np.float16(0.1)
print(f"小数精度: 0.1 在float16中实际存储为: {small_number}")
# 在大数区域的精度
large_number = np.float16(50000)
next_number = np.nextafter(large_number, np.float16(60000)) #往60000这个方向找下一个数
print(f"\n大数精度: 在50000附近")
print(f"50000 存储为: {large_number}")
print(f"下一个可表示的数是: {next_number}")
print(f"精度间隔: {next_number - large_number}")
# 对比int16的精确性
print(f"\nint16精度: 50000 在int16中会溢出! 最大只能到{int16_max}")
print("\n4. 小数表示能力:")
# 这些在int16中都是非法的
decimal_numbers = [0.5, 3.14159, 0.001, -2.71828]
print("float16可以轻松表示的小数:")
for num in decimal_numbers:
as_float16 = np.float16(num)
print(f" {num} -> float16: {as_float16}")
# 尝试用int16存储小数会发生什么
int_version = np.int16(0.5)
print(f"int16(0.5) = {int_version} (被截断了!)")
print("\n5. 精度分布可视化:")
# 在不同数值区间测试精度
test_ranges = [
(0.001, 0.01, "极小正数区域"),
(1.0, 2.0, "小数区域"),
(1000, 1001, "中等数值区域"),
(30000, 30010, "大数区域")
]
for start, end, description in test_ranges:
print(f"\n{description} [{start} 到 {end}]:")
# 找到这个区间内相邻的可表示数
a = np.float16(start)
b = np.nextafter(a, np.float16(end))
gap = b - a
print(f" 相邻数间隔: {gap:.6f}")
print(f" 示例: {a} 和 {b} 之间没有其他float16值")
print("\n6. 实际应用场景:")
# 场景1:图像处理(适合float16)
print("图像处理 - 使用float16:")
pixel_values = np.array([0.1, 0.5, 0.9], dtype=np.float16)
print(f"像素值: {pixel_values}")
print(f"内存占用: {pixel_values.nbytes} 字节")
# 场景2:精确计数(必须用int16)
print("\n精确计数 - 使用int16:")
inventory = np.array([100, 200, 300], dtype=np.int16)
print(f"库存数量: {inventory}")
print(f"精确计算: 100 + 200 = {inventory[0] + inventory[1]}")
# 场景3:科学计算(float16的优势)
print("\n科学计算 - 极大和极小的数:")
scientific_numbers = np.array([6.022e-4, 1.496e4, 9.109e-5], dtype=np.float16)
print(f"科学数据: {scientific_numbers}")
运行后的输出是:
1. 数值范围对比:
int16 范围: [-32,768 到 32,767]
float16范围: [-6.5504e+04 到 6.5504e+04]
float16最小正数: 6.1035e-05
float16最大值 / int16最大值 ≈ 1.9990 倍
2. 二进制表示对比:
int16 1 (1): 0000000000000001
float16 1.0 (1.0): 0011110000000000
int16 -1 (-1): 1111111111111111
float16 -1.0 (-1.0): 1011110000000000
int16 -2 (-2): 1111111111111110
int16 -32768 (-32768): 1000000000000000
3. float16 精度实验 - 体验'不均匀刻度':
小数精度: 0.1 在float16中实际存储为: 0.0999755859375
大数精度: 在50000附近
50000 存储为: 49984.0
下一个可表示的数是: 50016.0
精度间隔: 32.0
int16精度: 50000 在int16中会溢出! 最大只能到32767
4. 小数表示能力:
float16可以轻松表示的小数:
0.5 -> float16: 0.5
3.14159 -> float16: 3.140625
0.001 -> float16: 0.0010004043579101562
-2.71828 -> float16: -2.71875
int16(0.5) = 0 (被截断了!)
5. 精度分布可视化:
极小正数区域 [0.001 到 0.01]:
相邻数间隔: 0.000001
示例: 0.0010004043579101562 和 0.0010013580322265625 之间没有其他float16值
小数区域 [1.0 到 2.0]:
相邻数间隔: 0.000977
示例: 1.0 和 1.0009765625 之间没有其他float16值
中等数值区域 [1000 到 1001]:
相邻数间隔: 0.500000
示例: 1000.0 和 1000.5 之间没有其他float16值
大数区域 [30000 到 30010]:
相邻数间隔: 16.000000
示例: 30000.0 和 30016.0 之间没有其他float16值
6. 实际应用场景:
图像处理 - 使用float16:
像素值: [0.1 0.5 0.9]
内存占用: 6 字节
精确计数 - 使用int16:
库存数量: [100 200 300]
精确计算: 100 + 200 = 300
科学计算 - 极大和极小的数:
科学数据: [6.022e-04 1.496e+04 9.108e-05]
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)