在Tcl中是否存在将数字从数字转换为dB的“原生”方式

时间:2013-04-14 08:11:38

标签: tcl

dB或decibel是一个单位,用于显示对数刻度的比率,特别是,我感兴趣的dB的定义是X(dB)= 20log(x)其中x是“正常”值,X(dB)是以dB为单位的值。当写一个代码在mil之间转换。 mm,我注意到如果我使用直接方法,即乘以单位之间的比率,我在相反的转换上得到小错误,即:to_mil [to_mm val_in_mil]不等于val_in_mil并且与mm相同。库units解决了这个问题,因为它所做的转换没有计算错误。但具体没有提供(或者我没有找到)在库中将数字转换为dB的选项。

是否有另一个库/命令可以将数字转换为dB和dB,而不会产生计算错误?

我做了一个使用直接数学转换的实验,我得到的是:

>> set a 0.005
0.005
>> set b [expr {20*log10($a)}]
-46.0205999133
>> expr {pow(10,($b/20))}
0.00499999999999

2 个答案:

答案 0 :(得分:4)

这都是精确的问题。我们经常会忘记浮点数不是实数(在数学意义上的ℝ)。

您需要多少个十进制数字?

例如,如果您只需要5个十进制数字,则舍入0.00499999999999将为您提供0.00500,这是您想要的。

由于舍入fp数字不是一件容易的事,并且可能会产生更多麻烦,您可能只是改变了确定两个数字是否相等的方式:

 >> set a 0.005
 0.005
 >> set b [expr {20*log10($a)}]
 -46.0205999133
 >> set c [expr {pow(10,($b/20))}]
 0.00499999999999
 >> expr {abs($a - $c) < 1E-10}
 1
 >> expr {abs($a - $c) < 1E-20}
 0
 >> expr {$a - $c}
 8.673617379884035e-19

您的示例中的数字可以被视为“相等”直至错误或10 -18 。请注意,这只是一个粗略的估计,而不是一个完整的解决方案。

如果您真的处理对数字错误传播敏感的问题,您可能会更深入地研究“数值分析”。文章What Every Computer Scientist Should Know About Floating-Point Arithmetic或者更好的是,这个网站:http://floating-point-gui.de可能是一个开始。

如果您需要更高的精度,您应该放弃“原生”要求。

你可以使用tcllib(http://tcllib.sourceforge.net/doc/bigfloat.html提供的BigFloat,甚至可以通过ffidl(http://elf.org/ffidl)使用GMP(GNU多精度算术库)。已经为它定义了一个接口:{{3 }}

答案 1 :(得分:1)

通过存储浮点数的方式,每个log10(...)不能完全对应一个pow(10,...)。所以你失去了精度,就像整数分区89/7和88/7都是12。

当你将一个值放入浮点格式时,你应该忘记了再次知道的确切值的能力,除非你保留旧的,精确的值。如果你想要1/200,则将它存储为整数1和整数200.如果你想要1/200的十对数,则将其存储为1,200和十对数已完成的信息它

你可以用2的平方根的前x个十进制数填充你的整个记忆,但它仍然不是你存储的2的平方根。