有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

安卓的java浮点到双精度转换

好的,这应该很简单。。。但我还是不明白。我正在为Android编写一个java程序,用于对浮点数组进行fft。在返回的复频谱上,我提取实部和虚部,以便计算一些参数,如幅值和相位。问题是我使用的libgdx fft变换使用float,但是大多数数学类操作使用double。这意味着我需要将float转换为double。 它在fft的实部上似乎工作得很好,但是,对于虚部,我得到精度误差,或者更确切地说,对于一个频率单元,我得到一个45.188522的虚部浮点值,但是,当我转换为双倍时,它变为-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]));
   }

我知道并尝试过安卓 FloatMath类,但是没有实现atan2,因此我不得不转换为double

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

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

但所有返回的都是-45.18852,而不是45.18852

^^^^^^^^^^^^原件

更多详情:

下面是我的src代码和对我感兴趣的人的用法

好的,我正在使用Ubuntu10.10和EclipseJDK,版本:HeliosServiceRelease2 Android SDK:来自安卓 developers的最新r10。 我是为安卓 1.6,API级别4编译的。 我使用libgdx进行fft,您可以在这里获得它,Libgdx并确保添加gdx。jar添加到libs中,并添加到构建路径库中。如果您为安卓 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 安卓.app.Activity;
import 安卓.os.Bundle;
import com.badlogic.gdx.audio.analysis.FFT;
import java.lang.String;
import 安卓.util.FloatMath;
import 安卓.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 安卓 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);

    }
  }

我不熟悉安卓开发和java,所以如果答案很明显或者我的语法很奇怪,请耐心等待。希望有人能解决这个问题


共 (3) 个答案

  1. # 1 楼答案

    可能想尝试Double.parseDouble(new String(tmpr[i]))而不是隐式强制转换:这应该不会有什么不同,但我见过类似于浮动的奇怪事情

  2. # 2 楼答案

    @digiphd

    这不是答案我谦虚地试图证明,Java环境将浮点转换扩展到双精度,或将双精度转换缩小到浮点,都没有错

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

    除此之外,我唯一能建议的就是仔细检查变量声明,并遵循在自己的行中声明每个变量的标准。。。并在声明每个变量时进行初始化,这样做的副作用是将每个变量“向下”移动到其可能的最小范围内;这通常被认为是一件“好事”,因为它最大限度地减少了在其他地方意外使用/修改变量的机会。这是“临时”变量的三倍

    “证据”是浮动的吗?总是这样吗?扩大到相等的两倍

    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:没有,正如预期的那样

  3. # 3 楼答案

    我想你会发现问题在于这句话:

    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是匹配的