2016-05-08 8 views
2

浮動小数点数(正の数を言う)をnumpy形式で使用しています。精度を下げるために、あらかじめ定義されたビット数の固定小数点数に変換したいと思います。あらかじめ定義されたビット数で浮動小数点数を固定小数点に変換するためのpythonの使用方法

たとえば、num4fixptを使用すると、数値3.1415926はmatlabで3.25になります。 整数部分は3ビット、小数部分は2ビットとなります。コマンドはnum2fixpt(3.1415926、sfix(5)、2 ^(1 + 2-5)、 'Nearest'、 'on')です。

は、私はあなたがIEEE浮動小数点表記がどのように機能するかを理解している場合は、それを行うことができますPythonの

+0

ここで最終目標は何ですか? –

+0

私は数字が高すぎないようにしたくありません。たとえば、固定小数点デジタル信号プロセッサを使用してケースをシミュレートする。私は浮動小数点数をより精度の低い固定小数点形式で保存したい。 – tuming1990

答えて

3

使用して同じことを行うことができます。基本的には、Python LONGに変換し、ビットごとの演算子を実行してから、逆に変換する必要があります。例:

import time,struct,math 
long2bits = lambda L: ("".join([str(int(1 << i & L > 0)) for i in range(64)]))[::-1] 
double2long = lambda d: struct.unpack("Q",struct.pack("d",d))[0] 
double2bits = lambda d: long2bits(double2long(d)) 
long2double = lambda L: struct.unpack('d',struct.pack('Q',L))[0] 
bits2double = lambda b: long2double(bits2long(b)) 
bits2long=lambda z:sum([bool(z[i] == '1')*2**(len(z)-i-1) for i in range(len(z))[::-1]]) 

>>> pi = 3.1415926 
>>> double2bits(pi) 
'0100000000001001001000011111101101001101000100101101100001001010' 
>>> bits2long('1111111111111111000000000000000000000000000000000000000000000000') 
18446462598732840960L 
>>> double2long(pi) 
4614256656431372362 
>>> long2double(double2long(pi) & 18446462598732840960L) 
3.125 
>>> 

def rshift(x,n=1): 
    while n > 0: 
     x = 9223372036854775808L | (x >> 1) 
     n -= 1 
    return x 

>>> L = bits2long('1'*12 + '0'*52) 
>>> L 
18442240474082181120L 
>>> long2double(rshift(L,0) & double2long(pi)) 
2.0 
>>> long2double(rshift(L,1) & double2long(pi)) 
3.0 
>>> long2double(rshift(L,4) & double2long(pi)) 
3.125 
>>> long2double(rshift(L,7) & double2long(pi)) 
3.140625 

これは、丸めではなく、ビット数を切り捨てます。 rshift関数が必要なのは、Pythonの右シフト演算子が空の左端のビットをゼロで埋めるためです。 IEEE浮動小数点hereの説明を参照してください。

1

あなたはインタプリタのオーバーヘッドの多くを生成する傾向があり、明示的な型変換せずにバイナリ固定精度に丸めることができます。

[ 1. 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2. ] 
[ 1. 1. 1.25 1.25 1.5 1.5 1.5 1.75 1.75 2. 2. ] 

import numpy as np 

n_bits = 2 
f = (1 << n_bits) 

a = np.linspace(1, 2, 11) 
a_fix = np.round(a*f)*(1.0/f) 

print a 
print a_fix 

結果の例では、numpyのを使用していますが、それはただのです例示的な値のリストを生成するのに便利です。 Pythonのは、内蔵のround単一の値に対して同じようにうまく動作します:F 1.0/fの両方が正確な浮動小数点表現を持っていることを

x=3.1415926 
x_fix = round(x*f)/float(f) 
print x_fix 

注意。したがって、乗算と除算は丸め誤差なしで正確です。 1.0/fを掛けることは、大きな配列の場合に直接分割するよりも約3倍高速です。

この手法では、整数部分のビット数は制御されないため、数値が大きすぎる場合は数値をキャッピングしたり折り返したりする場合は、ビットシフトを少しずつ行う必要があります。

関連する問題