当前位置: 首页 > backend >正文

Python快速入门专业版(七):整数与浮点数:Python数值类型的运算与精度问题(附解决方案)

在这里插入图片描述

目录

  • 引言:为什么数值类型是编程的“基石”
  • 1.整数(int):Python中“无限延伸”的数字
    • 1.1 整数的基本特性与表示方法
      • 表示形式:
      • 示例:不同进制的整数转换
      • 核心特性:
    • 1.2 整数的核心运算:从基础到进阶
      • 1. 基础算术运算
      • 代码演示:
      • 2. 赋值运算(结合算术运算)
      • 3. 位运算(对二进制位操作)
    • 1.3 整数的实用场景与注意事项
      • 最佳适用场景:
      • 注意事项:
  • 2.浮点数(float):带小数的数值类型与精度陷阱
    • 2.1 浮点数的表示与基本运算
      • 表示形式:
      • 代码示例:
      • 基础运算:
      • 自动类型转换:
    • 2.2 浮点数的精度问题:为什么0.1 + 0.2 ≠ 0.3?
      • 问题演示:
      • 根源:二进制与十进制的转换误差
      • 其他常见的精度问题:
    • 2.3 精度问题的解决方案:何时用float,何时用decimal?
      • 方案1:忽略微小误差(适合非精确场景)
      • 方案2:使用decimal模块(适合高精度场景)
      • decimal模块的基础用法:
      • 控制精度(保留小数位数):
      • 货币计算示例(保留2位小数):
      • 方案3:转换为整数计算(适合货币场景)
  • 3.整数与浮点数的深度对比与适用场景
    • 3.1 类型转换:int与float的相互转换
      • 1. 浮点数转整数:
      • 2. 整数转浮点数:
      • 3. 字符串转数值:
    • 3.2 特殊数值:inf、-inf与nan
      • 示例:
  • 4.实战案例:数值计算在实际开发中的应用
    • 案例1:计算圆的周长与面积(浮点数应用)
    • 案例2:处理货币交易(高精度需求)
  • 5.总结:如何正确选择数值类型?

引言:为什么数值类型是编程的“基石”

在编程世界中,数值计算是最基础也最核心的功能之一。无论是统计分析、游戏开发还是科学计算,都离不开对数字的处理。Python作为一门通用编程语言,提供了两种最常用的数值类型——整数(int)浮点数(float),它们分别对应数学中的整数和小数概念。

与其他语言(如C、Java)不同,Python的数值类型具有独特的灵活性:整数支持任意大小(不受内存限制),浮点数则遵循IEEE 754标准(但存在精度隐患)。本文将以Python 3.13.6为基础,系统讲解整数与浮点数的特性、运算规则,重点剖析浮点数精度问题的根源,并提供切实可行的解决方案,帮助开发者在实际项目中规避数值计算的“陷阱”。

1.整数(int):Python中“无限延伸”的数字

Python的整数类型(int)用于表示没有小数部分的数字,支持正负值,且最显著的特点是大小不受限制(仅受限于系统内存)。这意味着你可以在Python中轻松处理远超其他语言范围的大整数,而无需担心溢出问题。

1.1 整数的基本特性与表示方法

表示形式:

  • 十进制:最常用的形式,如0100-42
  • 二进制:以0b0B开头,如0b1010(对应十进制10);
  • 八进制:以0o0O开头,如0o17(对应十进制15);
  • 十六进制:以0x0X开头,如0x1F(对应十进制31)。

示例:不同进制的整数转换

# 二进制转十进制
print(0b1010)  # 输出:10# 八进制转十进制
print(0o17)    # 输出:15# 十六进制转十进制
print(0x1F)    # 输出:31# 十进制转其他进制(通过内置函数)
print(bin(10))  # 输出:0b1010(十进制10转二进制)
print(oct(15))  # 输出:0o17(十进制15转八进制)
print(hex(31))  # 输出:0x1f(十进制31转十六进制)

核心特性:

  • 任意大小:Python整数可以无限大,例如计算2 **1000会得到一个302位的整数,而不会像C语言那样发生溢出;
    -** 自动转换 :当整数与浮点数运算时,结果会自动转为浮点数(如5 + 3.0 = 8.0);
    -
    不可变性 **:整数一旦创建就不能被修改,任何运算都会产生新的整数对象。

1.2 整数的核心运算:从基础到进阶

Python支持丰富的整数运算,包括算术运算、赋值运算和比较运算,以下是开发中最常用的操作:

1. 基础算术运算

运算符描述示例结果
+加法10 + 515
-减法10 - 55
*乘法10 * 550
/除法(结果为float)10 / 33.333…
//整除(向下取整)10 // 33
%取余(模运算)10 % 31
**幂运算2 ** 101024

代码演示:

# 基础运算
a = 10
b = 3print(a + b)   # 加法:13
print(a - b)   # 减法:7
print(a * b)   # 乘法:30
print(a / b)   # 除法(结果为float):3.3333333333333335
print(a // b)  # 整除(向下取整):3
print(a % b)   # 取余:1
print(a **b)  # 幂运算(10的3次方):1000# 负数整除(注意:结果向下取整)
print(-10 // 3)  # 输出:-4(而非-3,因为-4比-3更小)
print(10 // -3)  # 输出:-4
print(-10 // -3) # 输出:3

2. 赋值运算(结合算术运算)

常用的复合赋值运算符可简化代码:

x = 5
x += 3   # 等价于 x = x + 3 → x=8
x *= 2   # 等价于 x = x * 2 → x=16
x //= 5  # 等价于 x = x // 5 → x=3(16//5=3)
print(x) # 输出:3

3. 位运算(对二进制位操作)

整数支持按位运算,常用于底层编程或性能优化:

# 位运算示例(二进制视角)
a = 0b1010  # 十进制10
b = 0b1100  # 十进制12print(bin(a & b))  # 按位与 → 0b1000(8)
print(bin(a | b))  # 按位或 → 0b1110(14)
print(bin(a ^ b))  # 按位异或 → 0b0110(6)
print(bin(~a))     # 按位取反 → -0b1011(-11)

1.3 整数的实用场景与注意事项

最佳适用场景:

  • 计数场景(如循环次数、用户数量);
  • 序号标识(如ID、索引);
  • 无需小数的精确计算(如整数加减乘除)。

注意事项:

  • 整除的方向//运算符始终向下取整(向负无穷方向),负数整除可能得到意外结果(如-10 // 3 = -4);
  • 大整数性能:虽然Python支持任意大整数,但极端大的整数(如10**100000)运算会消耗较多内存和CPU;
  • 类型转换:使用int()函数可将字符串或浮点数转为整数,例如int("123")=123int(3.9)=3(直接截断小数部分)。

2.浮点数(float):带小数的数值类型与精度陷阱

浮点数(float)用于表示带小数部分的数字,如3.14-0.001。Python的浮点数遵循IEEE 754标准(双精度,64位),这意味着它能表示的小数范围广,但存在精度有限的固有问题。

2.1 浮点数的表示与基本运算

表示形式:

  • 标准小数形式:如3.140.0-1.5
  • 科学计数法:以eE表示指数,如1e3(1000.0)、2.5e-2(0.025)。

代码示例:

# 浮点数表示
pi = 3.14159
avogadro = 6.022e23  # 阿伏伽德罗常数(6.022×10²³)
tiny = 1.23e-4       # 0.000123print(avogadro)  # 输出:6.022e+23
print(tiny)      # 输出:0.000123

基础运算:

浮点数支持与整数类似的算术运算,但结果始终为浮点数:

a = 2.5
b = 4.2print(a + b)  # 加法:6.7
print(a - b)  # 减法:-1.7
print(a * b)  # 乘法:10.5
print(a / b)  # 除法:0.5952380952380952
print(a **b) # 幂运算(2.5的4.2次方):37.21167892879017

自动类型转换:

整数与浮点数混合运算时,结果会自动转为浮点数:

print(5 + 3.0)   # 输出:8.0(int + float → float)
print(10 * 2.5)  # 输出:25.0(int * float → float)
print(7 // 2.0)  # 输出:3.0(整除结果仍为float)

2.2 浮点数的精度问题:为什么0.1 + 0.2 ≠ 0.3?

这是Python初学者最常遇到的“反直觉”问题:两个简单的小数相加,结果却不等于预期的小数。

问题演示:

print(0.1 + 0.2)  # 输出:0.30000000000000004(而非0.3)
print(0.1 + 0.2 == 0.3)  # 输出:False

根源:二进制与十进制的转换误差

计算机以二进制存储数据,而大部分十进制小数(如0.1)无法被二进制精确表示,只能存储近似值。

  • 十进制的0.1转换为二进制是一个无限循环小数:0.0001100110011...(循环“0011”);
  • 计算机只能保留有限位数(IEEE 754标准保留53位有效数字),因此会截断并近似;
  • 0.1和0.2的近似值相加后,误差被放大,导致结果不等于0.3。

其他常见的精度问题:

print(0.1 * 3)       # 输出:0.30000000000000004
print(1.1 + 2.2)     # 输出:3.3000000000000003
print(0.1 + 0.1 + 0.1)  # 输出:0.30000000000000004

2.3 精度问题的解决方案:何时用float,何时用decimal?

浮点数的精度问题并非Python独有,而是所有遵循IEEE 754标准的语言共同存在的现象。解决方案需根据场景选择:

方案1:忽略微小误差(适合非精确场景)

若业务允许微小误差(如科学计算、图形渲染),可通过指定精度比较而非直接判等:

# 方法:判断两个数的差值是否小于某个阈值(如1e-9)
def is_close(a, b, eps=1e-9):return abs(a - b) < epsprint(is_close(0.1 + 0.2, 0.3))  # 输出:True
print(is_close(0.1 * 3, 0.3))    # 输出:True

Python 3.5+还内置了math.isclose()函数,实现类似功能:

import math
print(math.isclose(0.1 + 0.2, 0.3))  # 输出:True

方案2:使用decimal模块(适合高精度场景)

对于需要精确计算的场景(如金融、货币计算),Python标准库的decimal模块提供了十进制浮点运算,可避免二进制转换误差。

decimal模块的基础用法:

from decimal import Decimal# 用字符串初始化Decimal(避免直接用float传入,否则仍有误差)
a = Decimal('0.1')
b = Decimal('0.2')print(a + b)  # 输出:0.3(精确计算)
print(a + b == Decimal('0.3'))  # 输出:True# 浮点数与Decimal的对比
print(0.1 + 0.2)              # 输出:0.30000000000000004
print(Decimal(0.1) + Decimal(0.2))  # 注意:用float初始化仍有误差 → 0.3000000000000000166533453694

控制精度(保留小数位数):

通过getcontext().prec设置全局精度(有效数字位数):

from decimal import Decimal, getcontext# 设置全局精度为4位有效数字
getcontext().prec = 4c = Decimal('1.23456')
d = Decimal('2.34567')print(c + d)  # 输出:3.580(4位有效数字)
print(c * d)  # 输出:2.896(1.23456×2.34567≈2.896)# 重置为默认精度(28位)
getcontext().prec = 28

货币计算示例(保留2位小数):

from decimal import Decimal, ROUND_HALF_UP# 商品价格
price = Decimal('9.99')
# 数量
quantity = Decimal('3')
# 计算总价
total = price * quantity  # 29.97# 加税(税率8.25%)
tax_rate = Decimal('0.0825')
tax = total * tax_rate  # 2.472525# 四舍五入保留2位小数(适合货币)
total_with_tax = (total + tax).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)print(f"总价(含税费):{total_with_tax}")  # 输出:32.44

方案3:转换为整数计算(适合货币场景)

另一种避免小数的思路是:将所有金额单位转为“分”(或更小单位),用整数计算后再转换回原单位。

# 以“分”为单位(避免小数)
price_cents = 999  # 9.99元 = 999分
quantity = 3
total_cents = price_cents * quantity  # 2997分tax_rate = 0.0825  # 税率8.25%
tax_cents = int(total_cents * tax_rate)  # 2997×0.0825≈247分total_with_tax_cents = total_cents + tax_cents  # 3244分# 转换回元(保留2位小数)
total_with_tax = total_with_tax_cents / 100
print(f"总价(含税费):{total_with_tax:.2f}")  # 输出:32.44

3.整数与浮点数的深度对比与适用场景

特性整数(int)浮点数(float)
表示范围任意大小(受内存限制)约±1.7×10³⁰⁸(超出范围为inf)
精度完全精确存在二进制转换误差(不精确)
运算速度快(无精度处理开销)较慢(需处理小数部分)
内存占用随数字大小动态变化固定8字节(64位)
适用场景计数、序号、精确整数运算科学计算、图形学(允许误差)
转换函数int(x)(截断小数)float(x)

3.1 类型转换:int与float的相互转换

1. 浮点数转整数:

使用int()函数,直接截断小数部分(非四舍五入):

print(int(3.9))    # 输出:3(截断小数)
print(int(-2.5))   # 输出:-2
print(int(5.0))    # 输出:5(整数浮点数可精确转换)

2. 整数转浮点数:

使用float()函数,结果为带.0的浮点数:

print(float(10))   # 输出:10.0
print(float(-5))   # 输出:-5.0

3. 字符串转数值:

需注意字符串格式是否合法:

print(int("123"))    # 输出:123
print(float("3.14")) # 输出:3.14
print(float("1e3"))  # 输出:1000.0# 错误示例(格式不合法)
# print(int("3.14"))  # ValueError: invalid literal for int() with base 10: '3.14'

3.2 特殊数值:inf、-inf与nan

浮点数有三个特殊值,用于表示极端情况:

  • inf:正无穷大(大于任何数);
  • -inf:负无穷大(小于任何数);
  • nan:非数字(Not a Number,如0/0、sqrt(-1))。

示例:

import math# 无穷大
print(1e400)        # 输出:inf(超过最大表示范围)
print(-1e400)       # 输出:-inf
print(math.inf > 10**100)  # 输出:True# 非数字
print(0 / 0)        # ZeroDivisionError(Python中直接报错)
print(math.sqrt(-1)) # 输出:nan(复数的平方根)
print(float('nan')) # 输出:nan# 注意:nan与任何值(包括自身)都不相等
print(math.nan == math.nan)  # 输出:False

4.实战案例:数值计算在实际开发中的应用

案例1:计算圆的周长与面积(浮点数应用)

import mathdef circle_calculator(radius):"""根据半径计算圆的周长和面积"""if radius <= 0:raise ValueError("半径必须为正数")circumference = 2 * math.pi * radius  # 周长=2πrarea = math.pi * radius **2           # 面积=πr²return {"radius": radius,"circumference": round(circumference, 2),  # 保留2位小数"area": round(area, 2)}# 测试
result = circle_calculator(5.5)
print(f"半径:{result['radius']},周长:{result['circumference']},面积:{result['area']}")
# 输出:半径:5.5,周长:34.56,面积:95.03

案例2:处理货币交易(高精度需求)

from decimal import Decimal, ROUND_HALF_UPdef calculate_total(price, quantity, tax_rate):"""计算含税费的总价(精确到分)"""# 转换为Decimal类型(用字符串初始化)price = Decimal(str(price))quantity = Decimal(str(quantity))tax_rate = Decimal(str(tax_rate))# 计算subtotal = price * quantitytax = subtotal * tax_ratetotal = subtotal + tax# 四舍五入到分(保留2位小数)total_rounded = total.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)return {"subtotal": subtotal,"tax": tax,"total": total_rounded}# 测试:单价9.99元,数量3,税率8.25%
transaction = calculate_total(9.99, 3, 0.0825)
print(f"小计:{transaction['subtotal']}元")   # 输出:29.97元
print(f"税费:{transaction['tax']}元")       # 输出:2.472525元
print(f"总计:{transaction['total']}元")     # 输出:32.44元

5.总结:如何正确选择数值类型?

整数和浮点数是Python数值计算的基础,选择正确的类型和处理方式,能避免大多数数值问题。总结如下:

1.** 优先使用整数**:
当数据是整数(如计数、ID)或需要精确计算时,用int类型,避免引入浮点数的精度误差。

  1. 谨慎使用浮点数
    浮点数适合科学计算、图形学等允许微小误差的场景,使用时避免直接比较相等,改用math.isclose()

  2. 高精度场景必用decimal
    金融、货币等对精度要求极高的场景,必须使用decimal模块,并用字符串初始化Decimal对象。

  3. 特殊场景的替代方案
    货币计算可转换为整数(以“分”为单位),避免小数运算;超大整数运算需注意性能影响。

掌握数值类型的特性,不仅能写出更准确的代码,更能理解计算机处理数字的底层逻辑——这是从“会用”到“精通”的关键一步。在实际开发中,应始终根据业务需求选择合适的数值类型和处理方式,让数值计算既高效又可靠。

http://www.xdnf.cn/news/20334.html

相关文章:

  • 项目中的一些比较实用的自定义控件
  • Python文件打包为EXE的工具v1.0
  • 《AI大模型应知应会100篇》第67篇 Web应用与大模型集成开发实践——1小时打造国产大模型智能客服系统
  • MySQL问题5
  • github上传步骤
  • 季度最强策略:年化247%,回撤10%,夏普比率3.79。附大小盘轮动策略python源代码。
  • Nestjs框架: 使用 CASL 库实现基于角色的权限控制(RBAC)与细粒度访问控制的实战演示
  • 【嵌入式C语言】七
  • 【IQA技术专题】 多尺度的transformer网络IQA:MUSIQ
  • GO语言的主要语法和特性
  • 跨平台游戏引擎 Axmol-2.8.1 发布
  • 突破反爬限制:动态IP轮换策略与实现
  • XXL-JOB源码分析(服务端)
  • “唐人街大赛第二届”题解
  • Spring Boot 3.x 的 @EnableAsync应用实例
  • 基于51单片机的信号发生器函数发生器设计
  • 存储卡备用区用尽,拷贝机设置坏块数量又有何意义?
  • hot100-贪心算法(附图解思路)
  • 项目升级--Nginx
  • 一种基于迁移学习的零样本故障诊断方法
  • WSL2环境下因服务器重装引发的SSH连接问题排查记录
  • fastapi通过sqlmodel连接Mysql实现crud功能
  • 如何进行神经网络的模型训练(视频代码中的知识点记录)
  • 2025最新超详细FreeRTOS入门教程:第一章 FreeRTOS移植到STM32
  • dp算法的种类
  • 制衣跟单高效管理软件推荐
  • linux 安全与防护,全方向讲解
  • 华清远见25072班I/O学习day6
  • Qt绘图功能学习笔记
  • 北斗导航 | 导航定位中的卡尔曼滤波算法:原理、公式及C代码详解