【发布时间】:2021-12-18 06:40:38
【问题描述】:
我正在编写一个简单的程序来确定两个音高之间的音分差异;一分等于半音的 1/100。在比较音高时,最好用分来处理,因为频率刻度是对数的,而不是线性的。理论上,这是一个简单的计算:确定两个频率之间的音分数的公式是:
1200 * log2(pitch_a / pitch_b)
我写了一小段代码来自动化这个过程:
import numpy as np
import math
def cent_difference(pitch_a, pitch_b)
cents = 1200 * np.abs(math.log2(pitch_a / pitch_b))
return cents
当我给程序八度音阶时,这很有效:
In [28]: cent_difference(880, 440)
Out[28]: 1200.0
...但是在完美的五度音上差了大约 2 美分:
In [29]: cent_difference(660, 440)
Out[29]: 701.9550008653875
...并且随着我的前进而变得更糟,在大三度上损失了大约 14 美分:
In [30]: cent_difference(550, 440)
Out[30]: 386.31371386483477
这都是浮点精度的废话吗?为什么完美的第五个例子高估了美分,而主要的第三个例子却低估了美分?这是怎么回事?
非常感谢任何帮助!
【问题讨论】:
-
你为什么在这里使用
numpy??? -
无论如何,是的,不要指望使用浮点数的精确值。请改用
decimal.Decimal对象。虽然,如果你实际上需要numpy,那可能是个问题 -
浮点数不能准确表示实数。实数的数字表示不可能每一个都无限精确,但即使是相当精确的标准浮点数也很难。您可以使用精度更高的数据类型(以及在其上定义的操作)或使用不会深入池中并保持足够精确以满足您的需求的算法。
-
@juanpa.arrivillaga 并且同样迂腐,我没有说过没有实数可以精确表示。 显然“0”是那个愚蠢陈述的反例。您的回答还忽略了这样一个事实,即实际上无法表示的实数比可以表示的实数要多得多——它们是一个不断减少的分数,因此您的评论毫无意义。
-
@juanpa.arrivillaga:关于“实际问题”:正如我们在答案中看到的,浮点舍入不是这里的实际问题。请不要仅仅因为某些问题涉及浮点运算就认为浮点舍入是问题所在。这不应该是对任何浮点问题的下意识评论。
标签: python floating-accuracy logarithm pitch