float16和int16的表达实践

举报
黄生 发表于 2025/11/13 16:08:42 2025/11/13
【摘要】 在完成了解析学习之后,我们来做个实践编程,代码如下: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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。