正如用户
jdamp
指出的那样,这些数字过大,无法表示为 16 位整数值。我不知道您问题的背景,但了解到可以对数字进行简单重新缩放可能会有所帮助。
import math
import numpy as np
def scale_to(x, x_min, x_max, t_min, t_max):
"""
Scales x to lie between t_min and t_max
Links:
https://stats.stackexchange.com/questions/281162/scale-a-number-between-a-range
https://stats.stackexchange.com/questions/178626/how-to-normalize-data-between-1-and-1
"""
r = x_max - x_min
r_t = t_max - t_min
assert(math.isclose(0,r, abs_tol=np.finfo(float).eps) == False)
x_s = r_t * (x - x_min) / r + t_min
return x_s
将这些相当大的值转换为16位格式,看起来会像这样:
array_float = np.array([31784960.12, 69074944.12, 165871616.34])
scaled_array = scale_to(array_float,np.min(array_float),np.max(array_float), -32768,32767)
array_int16 = scaled_array.astype(np.int16)
-32768和32767是16位表示的最大值和最小值。这些数值代表了输入数组的最小和最大值,所有其他值都在其间缩放。然后才进行类型转换。因此,以上数值的输出结果如下:
array_int16
array([-32768, -14542, 32767], dtype=int16)
请注意,我更改了输入为浮点数,只是为了展示这也可以用浮点数完成。
如果我们记住原始数组的最小值和最大值,这些数字就可以被缩放回接近其原始值。
def scale_inv(x_s, x_min, x_max, t_min, t_max):
"""
Inverse scaling
Links:
https://stats.stackexchange.com/questions/281162/scale-a-number-between-a-range
https://stats.stackexchange.com/questions/178626/how-to-normalize-data-between-1-and-1
"""
r = x_max - x_min
r_t = t_max - t_min
assert(math.isclose(0,r_t, abs_tol=np.finfo(float).eps) == False)
x = (x_s - t_min) * r / r_t + x_min
return x
inv = scale_inv(array_int16.astype(float), np.min(array_float), np.max(array_float), -32768.0, 32767.0)
最后一行给我们返回了原始值,但存在一些舍入误差:
array([3.17849601e+07, 6.90759252e+07, 1.65871616e+08])
原始值为:31784960.12、69074944.12、165871616.34(如上所示的代码)
这在音频文件转换中可能很有用。根据您的上下文,这可能会有所帮助。(如果简单的缩放和类型转换不是您要寻找的,那么也许您需要查看 resampling
)
请记住,由于 jdamp
给出的原因,总会涉及到一些信息损失,这是无法避免的。类比一下:通常你不能把一个装满东西的大盒子里的所有物品都塞进一个小盒子里。
P.S.:有关缩放,请特别参见此链接:min-max-scaler 代码的评论中还提供了另一个链接。
int64
。考虑到一个16位整数只能管理最多65,535个值,而你所有的输入都超过了这个范围,那么你希望在第二个数组中找到什么值呢? - Mark Setchell