当旧值为零时如何计算百分比

56

我需要针对以下情况给出逻辑。我对此毫无头绪。

假设1月份我有10美元的收入,2月份我有20美元的收入。

我的增长率((20-10)/10)*100% = 100%

如果3月份我的收入是0美元

那么我的增长率((0-10)/10)*100% = -100%。我应该把这称为负百分比吗?(我知道这是紧缩)

更进一步,

如果现在4月份我有20美元的收入。

现在我如何计算增长率呢?当然,下面的公式是错误的:((20-0)/0)*100% = ?????

我的基本问题是:

  1. 是否有更好的解决方案来找到增长率,而不是上面的方法?

  2. 如果我使用上述公式,我是否应该将某个值作为参考?还是这也是错误的?


1
这个问题不适合讨论,因为它并不是一个编程问题。首先明确你想要做什么,然后 Stack Overflow 将会帮助你完善代码以实现你的需求。 - High Performance Mark
1
@HighPerformanceMark 我知道如何在程序中实现...我只需要逻辑就可以了... - sam
6
你是在暗示逻辑不属于编程吗?我认为你的意思是这不是一个编码问题,而是一个编程问题。 - mcwyrm
2
正确的方式来显示分母为0的计算结果并不是一个编程决策。 - High Performance Mark
4
我认为我们必须在这方面持不同意见。仅仅因为一个程序员做某件事情并不意味着它就是编程。以这个问题为例,它不需要编写代码,也不需要编程技能,而且可以在电脑前面之外完成。当然,一个程序员可能最终会去做,但我认为这并不是决定它是否属于编程非常重要的因素。 - Chris
显示剩余4条评论
12个回答

53
这绝对是一个编程问题。问题在于它本质上无法被编程。当P实际上为零时,百分比变化的概念就没有意义了。从零到任何数都不能表示为速率,因为它超出了速率的定义边界。从“不存在”到“存在”不是一种“变化”,而是一种“创造”。

35
我喜欢这个短语:“从‘不存在’到‘存在’不是一种存在上的改变,而是一种存在的创造。” 这句话有很多含义 :) - Kiel
5
绝对是编程语言中的莎士比亚! - Anoop Thiruonam

23
如果需要以百分比显示增长率,通常在这种情况下会显示[NaN]或类似的内容。而增长率将以每月$的形式报告。因此,在您的示例中,对于四月份,增长率将被计算为((20-0)/1)。
无论如何,确定正确的报告此特殊情况的方法是用户决策。您的用户需求是否涵盖了这一点?

所以你的意思是如果分母为'0',那么我就用1来替换它?对吗?我理解得对吗? - sam
3
不行。如果分母是“0”,则您的计算结果不是一个数字,需要单独处理。另一方面,如果您想报告增长,则应使用不同的计算方法。具体来说,您应该将$(收入、利润、支出等)的差异除以时间(小时、天、月等)的差异。 - mcwyrm
3
但是(这非常重要),在计算结果的分母为0时,正确的显示方式不是编程决定,而是用户决定。没有人能够告诉你正确的做法;请向你的用户询问。 - mcwyrm

16

从0到任何其他数字都没有增长率。也就是说,从零到大于零没有增长百分比,从零到小于零(负数)也没有减少百分比。在这种情况下,您需要决定的是当出现此情况时要输出什么。以下是我认为可以使用的两个选项:

  1. 每当您需要显示从零开始的增长率时,请输出无穷大符号 (∞)。Alt + 236 是该符号在数字键盘上的代码。您还可以将负无穷 (-∞) 用于从零开始的负增长率。
  2. 输出类似“[从零开始增加/减少]”之类的语句。

不幸的是,如果您需要进一步计算增长率,则上述选项将无法使用。但是,在任何情况下,任何数字都会给您的后续计算提供不正确的数据,所以这一点并不重要。您需要更新您的后续计算以应对此情况。

顺便说一下,当新旧值都为零时,((新-旧)/旧)函数将无法使用。您应该创建一个初始检查,以查看两个值是否都为零,如果是,则输出零百分比作为增长率。


10
如何在计算百分比变化时处理零取决于研究人员,并需要一些领域专业知识。如果研究人员认为这不会扭曲数据,可以简单地添加一个非常小的常数以消除所有零值。例如,在处理交易量时可能不希望这样做,因为交易量=0仅意味着资产根本没有交易。当逻辑上无法给所有值都加上小常数时,这是我首选的策略。考虑百分比变化公式((新-旧)/旧)*100。如果新值=0,则百分比变化将为-100%。只要它是序列中最小的百分比变化(这确实保证是序列中最小的百分比变化),这个数字确实具有财务意义。为什么呢?因为它显示出交易量经历了最大可能的减少,即从任何数字到0的过程,-100%。所以,我可以接受这个值存在于我的百分比变化序列中。如果我对该序列进行归一化,那就更好了,因为这个(可能)相对较大的绝对值将与其他变量在相同的比例尺上进行分析。但如果旧值=0怎么办?那就更难处理了。由于从0到1和从0到一百万的百分比变化相等,所以把它们都称为“无穷大”的百分比变化是有问题的。在这种情况下,我会将无穷大设置为np.nan并对它们进行插值。下面的图显示了我上面讨论的内容。从序列1开始,我们得到了序列4,该序列已准备好进行分析,没有Inf或NaN。

enter image description here

还有一件事:很多时候,计算百分比变化的原因是为了使数据平稳。因此,如果您的原始序列包含零并且希望将其转换为百分比变化以实现平稳性,请确保它尚未平稳。因为如果已经平稳,您就不必计算百分比变化。问题是取值为0的系列(OP所遇到的问题)很可能已经平稳,例如我上面考虑过的交易量系列。想象一个在零上下振荡的系列,在某些时刻达到0。这样的系列很可能已经平稳。

1
我想要补充的一点是,如果您连续有多个零,则此策略效果最佳。如果您有多个零,则会连续出现多个-100,这将没有意义,因为从一个-100到下一个实际上是0%的变化,而不是-100%。 - Saeed
这似乎非常有帮助,因为非常小的更改并没有产生重大影响,谢谢。 - Kalpana

3

你可以给每个例子加1。

(1+新) - (旧+1) / (旧+1)

5/ 1 * 100 ==> 500%


1
如果Old的值为-1呢? - Monty
以上代码存在一些严重的括号/求值顺序问题。 - Michael Tiemann
如果New等于0.1会怎么样? - Julius Delfino
同样的事情 0.1/1 x 100 ==> 10% - Amed

2

有几件事情需要考虑。

如果你的增长率为0,那么从0开始的变化也将为0。因此在这个意义上是有意义的。您可以通过添加一个小数字来进行调整,使得它从0.1到0.1的变化。然后变化和百分比变化将为0和0%。

然后考虑一下你从0变成20的情况。这样做会导致大量的报告问题。根据您选择添加的小数,例如如果您使用0.1或0.001,则您的百分比变化将相差100倍。因此,这种做法存在问题。

但是如果您从1到20变化,则%变化将为19/1=1900%。在这种情况下,%变化并没有太多意义,因为当您起点很低时,它会对任何变化非常敏感,并且可能会扭曲您的结果,如果其他数据点处于不同的比例尺上。

因此,重要的是要了解您的数据以及在这种情况下,您的数据中出现0和极端数字的频率。


0
function percentChange(initialValue, finalValue) {
    if (initialValue == 0 && finalValue == 0) {
        return 0
    } else if (initialValue != 0 && finalValue != 0) {
        return (finalValue / initialValue) - 1
    } else {
        return finalValue > initialValue ? 1 : -1
    }
}

0

应该是(新值减旧值)除以旧值和新值的平均数 当两个值都为零时有特殊情况


0

应该使用 float('inf') * new_value。 这样比较时会更好,因为与 float('NaN') 进行比较除了!= 以外总是返回False,因为它不与任何值匹配。


0
为了进行插值,对于两个月之间的情况: month2=((month3-month1)/2) + month1
诱人的做法是将零值加1,然后继续进行计算,但这样会使得任何具有比率/速率的数值异常巨大,所以不要这样做。

检查旧的读数是否等于零,如果是,则将每个数加1。 - Matthew Tranmer

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