浮动到双重转换为Android

时间:2011-04-30 04:41:57

标签: java android floating-point double fft

好的,所以这应该很简单......但我仍然无法理解。我正在用Java编写一个程序来获取浮点数组的fft。在返回的复频谱上,我提取实部和虚部,这样我就可以计算一些参数,如幅度和相位。问题是libgdx fft转换我正在使用float,但是大多数Math类操作都使用double。这意味着我需要将float转换为double。 它似乎在fft的Real组件上运行良好,但是假想我得到精度误差,或者说我得到一个频率bin我得到一个假想的浮点值45.188522然而,当我转换为double时它变为-45.188522

   fft.forward(array);
   fft_cpx=fft.getSpectrum();
   tmpi = fft.getImaginaryPart();
   tmpr = fft.getRealPart();
   for(int i=0;i<array.length/2;i++)
   {
       real[i] = (double) tmpr[i];
       imag[i] = (double) tmpi[i];  // THIS CONVERSION
       mag[i] = (float)Math.sqrt((real[i]*real[i]) + (imag[i]*imag[i]));
       phase[i] = (float) ((float) Math.atan2(imag[i], real[i]));
   }

我知道并尝试过android FloatMath类,但是没有实现atan2所以我不得不转换为double。

我还尝试了一些不同的转换,例如:

 imag[i] = tmpi[i];
 imag[i] = Double.parseDouble(Float.toString(tmpi[i])); // Of course you loose accuracy

但是所有人仍然返回-45.18852而不是45.18852

^^^^^ ORIGINAL ^^^^^^

更多细节:

以下是我的src代码和感兴趣的用法。

好的,我正在使用带有eclipse JDK的Ubuntu 10.10,版本:Helios Service Release 2 Android SDK:来自android developers的最新r10。 我正在为Android 1.6,API级别4编译。 我正在使用libgdx来获取fft,Libgdx并确保将gdx.jar添加到libs并添加到构建路径库中。如果您使用相同或新的Android 1.6活动创建一个新项目,设置AVD,我设置的AVD具有以下支持(包含为完整性):

SD Card yes
Accellerometer yes
DPas Support yes
Abstracted LCD Density 240
Audio Playback Support yes 
Max VM Application heap size 24
camera support no
Touch Screen support yes

这是我的src代码:

package com.spec.example;
import android.app.Activity;
import android.os.Bundle;
import com.badlogic.gdx.audio.analysis.FFT;
import java.lang.String;
import android.util.FloatMath;
import android.widget.TextView;

public class spectrogram extends Activity {
/** Called when the activity is first created. */
float[] array = {1, 6, 1, 4, 5, 0, 8, 7, 8, 6, 1,0, 5 ,6, 1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float[] array_hat,res=new float[array.length/2];
float[] fft_cpx,tmpr,tmpi,mod_spec =new float[array.length/2];
float[] real_mod = new float[array.length], imag_mod = new float[array.length];
double[] real = new double[array.length], imag= new double[array.length];
double[] mag = new double[array.length] ,phase = new double[array.length];
int n;
float tmp_val;
String strings;
FFT fft = new FFT(32, 8000);
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView tv = new TextView(this);

   fft.forward(array);
   fft_cpx=fft.getSpectrum();
   tmpi = fft.getImaginaryPart();
   tmpr = fft.getRealPart();
   for(int i=0;i<array.length;i++)
   {
       real[i] = (double) tmpr[i];   // This works well
       imag[i] = (double) tmpi[i];  // However this is creates a problem
       //mag[i] = FloatMath.sqrt((tmpr[i]*tmpr[i]) + (tmpi[i]*tmpi[i]));   //using FloatMath android class (works fine)
       mag[i] = Math.sqrt((real[i]*real[i]) + (imag[i]*imag[i]));
       phase[i]=Math.atan2(imag[i],real[i]);

       /****Reconstruction****/        
       real_mod[i] = (float) (mag[i] * Math.cos(phase[i]));
       imag_mod[i] = (float) (mag[i] * Math.sin(phase[i]));

   }

   fft.inverse(real_mod,tmpi,res);// inverse fft to reconstruct original array if input = output It works as it is, however it is using the input imaginary, not imag_mod
   strings=String.valueOf(tmpi[1]); // Just printing the second imaginary element Calculated using: |X|e^(j*phaseofX) = |X|(cos(X) + jsin(X))
   //strings=String.valueOf(imag_mod[1]); // Just printing the second imaginary element (Original returned from fft.getImaginary())
    //this ^^ is the one which returns a -ve (Uncomment to test)
   tv.setText(strings);
   setContentView(tv);

    }
  }

我是android开发和java的新手,所以如果答案看起来很明显或者我的语法看起来很奇怪,请耐心等待。希望有人能解决这个问题......

3 个答案:

答案 0 :(得分:2)

可能想尝试Double.parseDouble(new String(tmpr[i]))而不是隐式演员:它应该没有什么区别,但是我看到了类似浮动的奇怪事情。

答案 1 :(得分:2)

我想你会发现问题就在这一行:

float[] fft_cpx,tmpr,tmpi,mod_spec = new float[array.length/2];

我认为你只是实例化一个数组,如果用以下代码替换它:

float[] fft_cpx = new float[array.length/2];
float[] tmpr = new float[array.length/2];
float[] tmpi = new float[array.length/2];
float[] mod_spec = new float[array.length/2];

从而创建一些单独的对象,你会发现tmpi和img匹配。

答案 2 :(得分:1)

@digiphd,

这不是一个答案... 这是我谦虚地尝试证明Java环境没有任何问题,从而扩大了从float到double的转换,或者从double到float的缩小转换。

请您在您的环境中运行此测试(或等效测试)吗?

除此之外,我唯一能建议的是DOUBLE CHECK你的变量声明,并遵循在自己的行上声明每个变量的标准......并初始化为你声明每个变量,它有侧面 - 将每个变量“向下”移动到其最小可能范围内的效果;这通常被认为是“好事”,因为它最大限度地减少了变量在某处意外使用/修改的机会 - 否则无意中。这对于“临时”变量来说是TRIPLE !!!

漂浮的

“证明”?总是?扩大到等于双

package forums;

import java.util.Random;

public class FunkyDouble
{
  private static final Random RANDOM = new Random();
  private static final int HOW_MANY = 100*1000*1000;
  private final static double EPSILON = 0.0000001; // 1/10^7

  public static void main(String... args) 
  {
    double d;
    float f;

    for (int i=0; i<HOW_MANY; i++) {
      d = randomDouble();
      f = (float) d;
      if ( Math.abs(d - f) > EPSILON ) {
        System.out.println("FunkyDouble A: Math.abs("+d+" - "+f+") = "+Math.abs(d - f));
      }

      f = randomFloat();
      d = f;
      if ( Math.abs(f - d) > EPSILON ) {
        System.out.println("FunkyDouble B: Math.abs("+f+" - "+d+") = "+Math.abs(f - d));
      }
    }
  }

  private static double randomDouble() {
    return RANDOM.nextDouble() * (RANDOM.nextBoolean() ? -1.0D : 1.0D);
  }

  private static float randomFloat() {
    return RANDOM.nextFloat() * (RANDOM.nextBoolean() ? -1.0F : 1.0F);
  }

}

<强>输出

C:\Java\home\src\forums>"C:\Program Files\Java\jdk1.6.0_16\bin\java.exe" -Xms4m -Xmx256m -enableassertions -cp c:\java\home\src;C:\Java\home\classes; forums.FunkyDouble
Press any key to continue . . .

IE:没有,正如所料。