我一直在尝试绘制十二音阶,从最低到最高的可听音调,以赫兹为单位
我找到了一种方法,使用一个始终正确的while循环,然后在音调低于或高于人类可听到的范围时使用break退出循环
我知道这种循环是一种不好的做法,但是作为一个新手程序员,我想不出如何用正确的方法来实现。如果不使用“while True”,如何实现相同的结果
我已尝试将条件“note>;highest或note<;lowest”放在while循环中,其中“True”当前位于while循环中,但是“note”仅在循环中定义,因此我得到了一个“NameError:name'note'未定义”错误
highest = 20000
lowest = 20
key = 440
TET = 12
equal_temper = [key]
i = 1
while True:
note = key * (2**(1/TET))**i
if note > highest or note < lowest:
break
equal_temper.append(note)
i += 1
i = 1
while True:
note = key * (2**(1/TET))**-i
if note > highest or note < lowest:
break
equal_temper.append(note)
i += 1
equal_tempered = sorted(equal_temper)
for i in range(len(equal_temper)):
print(equal_tempered[i])
终端的输出似乎是正确的。它的向下或向上取整可能与我见过的其他桌子不同。我只想知道如何做到这一点,而不使用“while True”
我注意到你让你的编译器一次又一次地重新做同样的计算,而它们只需要做一次!(这些都可以由您来完成)
您有一个用于注释值的设置公式:
note = key * ( 2 ** (1/TET) ) ** i
。这可以很容易地反转为i
作为note
:i = TET * log_2(note / key)
的函数来求解。有了这个,并且知道了注释的上限和下限,我们可以确定i
的边界插入上限,
20000
给出i=66.07
。高于此值的任何值都将导致注释大于上限,因此我们希望取此值的下限i_upper = 66
插入下限
20
,得到i=-53.51
。任何低于此值的值都将给出一个低于您的下限的注释,因此我们希望取此值的上限i_lower = -53
现在我们所要做的就是从
i_lower
循环到i_upper
,并用注释值填充数组这种方法避免了使用while循环,如果您更改任何参数,它很容易推广,并且只需通过构造,就可以返回一个已排序的数组,这样您就不必在以后对其进行排序
一些注意事项:
Log(x)/Log(B)
给出了X的日志基数B,而不管日志的原始基数是什么。这就是为什么我们在i_value
函数中除以math.log(2)
,它给出了N/key
的日志基数2字符串前面使用的字母
f
表示格式字符串,并将用它的计算结果替换{}
中的任何内容。例如,x=5; print(f"My x is {x}")
将打印My x is 5
。这个速记功能是python 3.6的新特性。如果您使用的是Python3.6之前的版本,则需要用较长的版本替换format语句:print("Number of notes above = {}".format(notes_above))
最后一个print语句使用
*
对equal_temper
注释列表进行“解包”,然后在每个元素之间使用换行符(\n
)进行打印你可以简单地写下
这样,您就可以将if语句中的条件的相反部分作为while循环的条件,并去掉硬编码的布尔值
编辑: 我对您的代码做了一些细微的修改,并得出以下结论:
当我在我的机器上运行它时,它会产生与代码相同的输出。你能检查一下吗
相关问题 更多 >
编程相关推荐