簡體   English   中英

android 的浮點到雙精度轉換

[英]Float to Double conversion for android

好的,所以這應該很簡單......但我仍然無法弄清楚。 我正在 java 中為 Android 編寫一個程序來獲取浮點數組的 fft。 在返回的復頻譜上,我提取了實部和虛部,以便計算一些參數,例如幅度和相位。 問題是我使用的 libgdx fft 變換使用浮點數,但是大多數數學 class 操作使用雙精度。 所以這意味着我需要將浮點數轉換為雙精度數。 它似乎在 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 class,但是沒有實現 atan2,所以無論如何我都被迫轉換為 double。

我還嘗試了一些不同的轉換,例如:

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

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

^^^^^ 原創 ^^^^^^

更多詳情:

下面是我的 src 代碼和感興趣的人的用法。

Ok, I am using Ubuntu 10.10 with eclipse JDK, Version: Helios Service Release 2 Android SDK: The latest r10 from android developers . I am compiling for android 1.6, API level 4. I am using libgdx for the fft you can get it here, Libgdx and ensure you add the gdx.jar to your libs and added to your build path libraries. 如果您為 android 1.6 創建一個具有相同或新活動的新項目,請設置一個 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

這是我的源代碼:

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 的新手,所以如果答案看起來很明顯或者我的語法看起來很奇怪,請耐心等待。 希望有人能解決...

可能想嘗試Double.parseDouble(new String(tmpr[i]))而不是隱式強制轉換:它不應該有所作為,但我已經看到了像浮點數這樣的奇怪事情。

我想你會發現問題出在這一行:

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 匹配。

@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);
  }

}

OUTPUT

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:沒有,正如預期的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM