python round四舍五入和decimal库精确四舍五入

文章目录

Python 的 decimal 库提供了高精度的十进制浮点数运算功能,特别适用于需要精确小数运算的场景,如金融计算。以下是 decimal 库和 Decimal 类中 quantize 方法的详解:

decimal 库概述

decimal 模块以三个核心概念为中心:十进制数(Decimal)、算术上下文(Context)和信号(Signals)。十进制数是不可变的,包含符号、系数数字和一个指数。算术上下文定义了精度、舍入规则等。信号用于处理计算中的异常条件。

Decimal 类

Decimal 类是 decimal 模块中用于表示十进制数的类。它支持从字符串、整数或浮点数创建 Decimal 对象,并进行精确的算术运算。

quantize 方法

quantize 方法用于将 Decimal 对象舍入到指定的精度。该方法接受一个 Decimal 对象作为参数,并根据该对象的值对原 Decimal 对象进行舍入。舍入后的值将具有与参数相同的指数(即小数点后的有效数字位数)。

用法
python 复制代码
from decimal import Decimal

# 创建 Decimal 对象
d = Decimal('123.456')

# 将 Decimal 对象舍入到小数点后两位
quantized_d = d.quantize(Decimal('0.01'))
print(quantized_d)  # 输出: 123.46
参数
  • quantizer:一个 Decimal 对象,指定了舍入的精度。
  • rounding:可选参数,指定舍入模式,默认为 ROUND_HALF_UP(四舍五入)。其他模式包括 ROUND_DOWN、ROUND_UP 等。
舍入模式
  • ROUND_HALF_UP:四舍五入,当要舍入的数字正好在两个可舍入的数字中间时,向上舍入到最近的较大值。
  • ROUND_DOWN:总是向下舍入。
  • ROUND_UP:总是向上舍入。
  • ROUND_HALF_DOWN:如果最后一个有效数字大于或等于 5,则向上舍入;否则向下舍入。
  • ROUND_HALF_EVEN:类似于 ROUND_HALF_DOWN,但如果最后一个有效数字为 5,则会检查前一位,偶数值会导致结果向下舍入,奇数值导致结果向上舍入。
其他常用方法
  • adjusted():返回调整后的指数,直到只剩下前导数字。
  • compare(other):比较两个 Decimal 实例的值。
  • copy_abs():返回参数的绝对值。
  • is_normal(context=None):如果参数是一个有限正规数,返回 True。
  • is_zero():如果参数是 0,则返回 True。
  • ln(context=None):返回操作数的自然对数(以 e 为底)。
  • log10(context=None):返回操作数的自然对数(以 10 为底)。
  • max(other, context=None):比较两个数值大小,并返回大的值。
  • min(other, context=None):比较两个数值大小,并返回小的值。

decimal 模块和 Decimal 类提供了强大的工具来处理需要高精度计算的场景,确保计算结果的准确性和可靠性。

举例

ROUND_HALF_UP 和 ROUND_HALF_DOWN 是两种不同的舍入模式,它们在处理数字中间值时的舍入行为有所不同。以下是这两种舍入模式的具体解释和示例:

ROUND_HALF_UP(四舍五入)

ROUND_HALF_UP 是最常用的舍入模式,当要舍入的数字正好在两个可舍入的数字中间时,它将向上舍入到最近的较大值。换句话说,如果舍入位后的数字是5或更大,就会向上舍入;如果小于5,则向下舍入。

示例:

  • round(2.5) 会得到 3,因为 .5 正好在 2 和 3 之间,按照 ROUND_HALF_UP 规则,向上舍入到 3。
  • round(3.5) 也会得到 4,同理,.5 使得 3 向上舍入到 4。
ROUND_HALF_DOWN(五舍六入)

ROUND_HALF_DOWN 是一种较少使用的舍入模式,它在处理数字中间值时,如果舍入位后的数字是5,则向下舍入到最近的较小值。

示例:

  • round(2.5) 会得到 2,因为 .5 使得 2 向下舍入到 2。
  • round(3.5) 会得到 3,因为 .5 使得 3 向下舍入到 3。

在 Python 的 decimal 模块中,可以通过设置 quantize 方法的 rounding 参数来指定舍入模式。以下是如何使用这两种舍入模式的示例:

python 复制代码
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN

# 创建 Decimal 对象
d = Decimal('123.5')

# 使用 ROUND_HALF_UP 模式舍入
rounded_up = d.quantize(Decimal('1'), rounding=ROUND_HALF_UP)
print(rounded_up)  # 输出: 124

# 使用 ROUND_HALF_DOWN 模式舍入
rounded_down = d.quantize(Decimal('1'), rounding=ROUND_HALF_DOWN)
print(rounded_down)  # 输出: 123

在这个示例中,123.5 使用 ROUND_HALF_UP 模式舍入后得到 124,而使用 ROUND_HALF_DOWN 模式舍入后得到 123。这展示了两种模式在处理 .5 这样的中间值时的不同行为。

round

Python 内置的 round 函数和 decimal 模块中的 Decimal 类的 quantize 方法都可以用来进行数值的四舍五入,但它们在默认行为上有所不同,并且 decimal 模块提供了更多的灵活性和精确控制。

Python 内置 round 函数
  • Python 3 中的 round 函数遵循"银行家舍入法"(也称为"偶数舍入法"),即当要舍入的数字正好在两个可舍入的数字中间时(例如 2.5 或 -2.5),它会舍入到最近的偶数。这意味着 round(2.5) 会得到 2,而 round(3.5) 会得到 4。
  • round 函数的行为可以通过指定第二个参数 ndigits 来控制舍入的位数,但舍入模式默认是 ROUND_HALF_TO_EVEN(即"银行家舍入法")。
decimal 模块中的 Decimal 类和 quantize 方法
  • decimal.Decimal 类的 quantize 方法默认遵循 ROUND_HALF_UP 舍入模式,即当要舍入的数字正好在两个可舍入的数字中间时,它会向上舍入到最近的较大值。这意味着 quantize(Decimal('2.5'), Decimal('1')) 会得到 Decimal('3')。
  • quantize 方法允许你指定舍入模式,例如 ROUND_HALF_DOWN、ROUND_HALF_EVEN(与 Python 内置 round 函数的默认行为相同)等。
对应关系

如果你想要使 Python 内置的 round 函数的行为与 decimal 模块中的某个舍入模式相对应,可以这样对应:

  • Python 内置 round 函数的默认行为(ROUND_HALF_TO_EVEN)对应于 decimal 模块中的 ROUND_HALF_EVEN。
  • 如果你想要 Python 的 round 函数行为与 decimal 模块中的 ROUND_HALF_UP 相对应,你需要手动实现这种舍入逻辑,因为 round 函数本身不提供直接的方式来改变其舍入模式。

以下是如何使用 decimal 模块来模拟 Python 内置 round 函数的默认行为的示例:

python 复制代码
from decimal import Decimal, ROUND_HALF_EVEN

# 创建 Decimal 对象
d = Decimal('2.5')

# 使用 ROUND_HALF_EVEN 模式舍入
rounded_value = d.quantize(Decimal('1'), rounding=ROUND_HALF_EVEN)
print(rounded_value)  # 输出: 2

在这个示例中,quantize 方法使用了 ROUND_HALF_EVEN 舍入模式,这与 Python 内置 round 函数的默认行为相匹配。

真正的四舍五入

在Python中,内置的round函数实际上执行的是"银行家舍入法"(ROUND_HALF_TO_EVEN),这意味着当数字正好位于两个整数的中间时,它会舍入到最近的偶数。例如,round(2.5)会得到2,而round(3.5)会得到4。

如果你想要实现真正的四舍五入,即当数字正好位于两个整数中间时向上舍入,你可以自定义一个函数来实现这个逻辑。以下是一个简单的实现:

python 复制代码
def true_round(number):
    if number - int(number) < 0.5:
        return int(number)
    else:
        return int(number) + 1

# 测试真正的四舍五入
print(true_round(2.5))  # 输出: 3
print(true_round(3.5))  # 输出: 4
print(true_round(4.5))  # 输出: 5

这个true_round函数检查数字的小数部分是否小于0.5。如果是,它就向下舍入;否则,它向上舍入。

如果你想要处理负数,可以稍微修改这个函数:

python 复制代码
def true_round(number):
    if number < 0:
        return int(number) - (1 if number % 1 else 0)
    else:
        return int(number) + (1 if number % 1 else 0)

# 测试真正的四舍五入,包括负数
print(true_round(2.5))  # 输出: 3
print(true_round(3.5))  # 输出: 4
print(true_round(-2.5)) # 输出: -3
print(true_round(-3.5)) # 输出: -4

在这个版本中,我们检查数字的符号,并相应地调整舍入逻辑。对于正数,如果小数部分大于0,则向上舍入;对于负数,如果小数部分大于0(即数字更接近于更小的整数),则向下舍入(实际上是向更负的方向舍入)。

相关推荐
晓得迷路了11 小时前
栗子前端技术周刊第 152 期 - Rspack 2.3、TypeScript 7.1 Beta、Bun 1.4.4...
前端·javascript·css
一级新生11 小时前
LLM _ Agent _ Skill _ 专家 的关系与选型笔记
java·开发语言·人工智能·笔记·大模型·智能体·skill
文丑颜不良啊11 小时前
LeetCode1541~1560题目解析
java·leetcode
普通人611 小时前
CSS-box-sizing-使用指南
开发语言·前端·css·1024程序员节
她说彩礼65万11 小时前
C# TaskCompletionSource
java·开发语言·c#
2601_9679791211 小时前
python中str函数怎么用?使用方法与注意事项详解
python·使用方法·字符串转换·注意事项·str函数
当战神遇到编程11 小时前
Java 基础入门(七):递归详解——执行原理、方法调用栈与经典练习
java
青少儿编程课堂11 小时前
蓝桥杯青少组图形化+信息素养+电子学会Scratch考级:校园口算闯关解析
c++·python·算法·bfs·信息学竞赛
风骏时光牛马11 小时前
AI开源工具一站式尝鲜体验
前端
2603_9696948511 小时前
【MySQL学习笔记】DQL(基础查询/条件/聚合/分组/排序/分页)与 DCL(用户权限)全解析
数据库·笔记·学习·mysql·学习方法