如何检查两个值之间的变化(以百分比表示)?

33

我有两个数值(之前的和当前的),我想检查它们之间的变化(以百分比表示):

(current/previous)*100

但如果先前的值为0,我会得到除以零的错误,并且如果值没有变化,我会得到100%。


4
如果先前的值为零且当前值不为零,则不能将变化计算为旧值的比例,这是一个普遍的数学原则,与编程无关。 - Hammerite
如果你想得到改变的百分比(“X% 更大”),而不是绝对的比较(“当前为先前的 X%”),那么你需要执行 (current/previous)*100 - 100。当然,这仍然不能让你除以零。 - TigerhawkT3
如果 current == previous,这不是表示变化为0%,而不是100%吗?如果从100变为80,根据您的用例,这是20%还是80%? - krethika
是的,正如楼主所说,当值不改变时,他们得到了100%,而他们不想要这样。我认为对于从100到80,他们想要-20%,这需要我上面提到的代码片段。 - TigerhawkT3
我投票关闭此问题,因为它涉及算术而非编程。 - High Performance Mark
9个回答

46
def get_change(current, previous):
    if current == previous:
        return 100.0
    try:
        return (abs(current - previous) / previous) * 100.0
    except ZeroDivisionError:
        return 0

编辑:有些人评论说OP描述的是当前代码的问题,而不是要求这种行为,因此在这里举一个例子:“如果当前值等于以前的值,则没有变化。您应该返回0”。此外,如果以前的值为0,我已经使该方法返回Infinity,因为当原始值为0时,不存在真正的百分比变化。

  def get_change(current, previous):
    if current == previous:
        return 0
    try:
        return (abs(current - previous) / previous) * 100.0
    except ZeroDivisionError:
        return float('inf')

4
如果当前值等于之前的值,则表示没有变化,应该返回0。 - Mureinik
根据所提出的问题,“如果值不改变,我得到100%”。 - Matt
3
OP在描述他目前代码中的问题,而不是要求这种行为。 - Mureinik
难道不应该是:return (abs(current - previous) / current ) * 100.0 - ascendedcrow
1
12值的变化为例,当前的响应是100,如果一个值翻倍了,它改变了100%,这是有意义的。但如果我们使用当前作为分母来实现它,它会给出一个50的响应,但是双倍增长并不是一个50%的变化。 - Matt
显示剩余3条评论

13

您需要将变化量(current-previous)除以previous,而不仅仅是当前值。简单来说:

change_percent = ((float(current)-previous)/previous)*100
请注意,如果previous0,则无论Python的实现如何,都无法计算百分比变化。

这不适用于所有值,请尝试将当前值设置为78752,上一个值设置为39408。我猜这是由于四舍五入造成的。 - Sven van den Boogaart
@SvenvandenBoogaart 不是四舍五入,而是整数除法。我的编辑应该解决了这个问题。 - Mureinik

8
def get_percentage_diff(previous, current):
    try:
        percentage = abs(previous - current)/max(previous, current) * 100
    except ZeroDivisionError:
        percentage = float('inf')
    return percentage

我发现了一个更好的方法。

只适用于不超过100%的差异。如果增加超过100%,则此解决方案将失败。


优秀的回答,我赞扬你的代码准确性和表达能力,它不会发生变异(导致算术错误)。 - joe hoeller
1
例如,之前是5,当前是15,这将返回66.66%,这对我来说似乎不正确(我预期的是+200%)。 - Programmierus
如果之前是50,现在是100,那么这个返回值是50,这是错误的。100是50的100%增加。 - Sandeep Balagopal
你说得对,这个解决方案只适用于百分比差在100%以下的情况,否则会失败。 - ruhi dağdelen
为什么这个回答有10个赞,而一个类似解决方案并且有适当归属的旧回答却只有0个赞? - undefined

4
为了涵盖所有“零”的情况,您可以在语句中使用三元运算符。
(current - previous) / previous * 100.0 if previous != 0 else float("inf") * abs(current) / current if current != 0 else 0.0

4

你应该除以前一个数的绝对值。 如果前一个数是负数且当前数也是负数,则如果在分母中不使用绝对值,将得到错误的结果。 例如,如果当前数字为-6,前一个数字为-5:

(-6 - (-5)) / -5 = 

(-6 + 5) / -5 =  

-1 / -5 = 20 %

这是明显错误的,因为在这种情况下百分比变化应该是负数-6 < -5。所以请使用以下函数:

def percentage_change(current, previous):
    if previous != 0 :
        return float(current - previous) / abs(previous) * 100
    else:
        return "undefined"

记住,如果你之前的数是零,那么零除以零是未定义的:https://en.wikipedia.org/wiki/Division_by_zero 此外,你不应该使用分子的绝对值代替分母。以下是一个例子:
先前的值:-5
当前的值:-4
| (-4 - (-5)) | / -5 = 
| (-4 + 5) | / -5 =  
|1| / -5 = 
1 / -5 = -20%

这是错误的,因为 -4 > -5

正确:

(-4 - (-5)) / | -5 | = 
(-4 + 5) / | -5 | =  
1 / 5 = 20%

参考资料:https://www.calculatorsoup.com/calculators/algebra/percent-change-calculator.php


2

I use this

  def pct_change(first, second):
    diff = second - first
    change = 0
    try:
        if diff > 0:
            change = (diff / first) * 100
        elif diff < 0:
            diff = first - second
            change = -((diff / first) * 100)
    except ZeroDivisionError:
        return float('inf')
    return change

1

这是从this网站纠正答案取公式:

def get_percentage_diff(previous, current):
    try:
        percentage = abs(previous - current)/((previous + current)/2) * 100
    except ZeroDivisionError:
        percentage = float('inf')
    return percentage
    
difference = get_percentage_diff(500,1750)

输出:111.111% 差异


0

我的解决方案:

def find_difference(a, b):
    return ((abs(a - b)) / ((a + b) / 2)) * 100

-1
我想最优化的方式应该是这样的。
def percentage_change(current,previous):
    if current and previous !=0:
       return round((current/previous)-1*100,2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接