java android的浮点到双转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5839569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 13:03:19  来源:igfitidea点击:

Float to Double conversion for android

javaandroidfloating-pointdoublefft

提问by digiphd

OK, so this should be simple... But I still can't figure it out. I am writing a program in java for Android to take the fft of a float array. On the complex frequency spectrum returned I extract the real and imaginary components so I can calculate some parameters such as magnitude and phase. The problem is the libgdx fft transform I am using uses float, however most of the Math class operations use double. So that means I need to convert float to double. It seems to work fine on the Real component of the fft, however with the imaginary I get precision errors, or rather I get for one frequency bin I get an imaginary float value of 45.188522 however, when I convert to double it changes to -45.188522.

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

I am aware and have tried the android FloatMath class, however there is no atan2 implemented so I am forced to convert to double regardless.

我知道并尝试过 android FloatMath 类,但是没有实现 atan2,所以无论如何我都被迫转换为 double。

I have also tried a few different conversions like:

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

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

But all still return a -45.18852 instead of 45.18852

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

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

^^^^^ 原版 ^^^^^^

More Detail:

更多详情:

Below is my src code and usage for those interested.

下面是我的 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, Libgdxand ensure you add the gdx.jar to your libs and added to your build path libraries. If you create a new project either with the same or new activity for android 1.6, set up a AVD, the one I have set up has the following support (included for completeness) :

好的,我将 Ubuntu 10.10 与 Eclipse JDK 一起使用,版本:Helios Service Release 2 Android SDK:来自android 开发人员的最新 r10 。我正在为 android 1.6,API 级别 4 编译。我正在使用 libgdx 作为 fft 你可以在这里得到它,Libgdx并确保你将 gdx.jar 添加到你的库中并添加到你的构建路径库中。如果您为 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

Here is my src code:

这是我的源代码:

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

    }
  }

I am new to android development and java, so please be patient with me if the answer seems obvious or my syntax seems odd. Hopefully someone work it out...

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

采纳答案by Femi

Might want to try Double.parseDouble(new String(tmpr[i]))instead of the implicit cast: it SHOULDN'T make a difference, but I've seen strange things like that with floats.

可能想尝试Double.parseDouble(new String(tmpr[i]))而不是隐式转换:它不应该有什么不同,但我见过像浮动一样的奇怪事情。

回答by NickT

I think you'll find the problem is this line:

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

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

I think you are only instantiating one array, if you replace it with:

我认为您只是实例化一个数组,如果您将其替换为:

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];

Thereby creating some separateobjects, you will find that tmpi and img match.

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

回答by corlettk

@digiphd,

@digiphd,

This isn't an answer...it's my humble attempt at a proof that there's nothing wrong with the Java environments widenning conversion from float to double, or the narrowing conversion from double to float.

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

Would you please run this test (or equivalent) in your environment?

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

Other than that, the only thing I can suggest is DOUBLE CHECK your variable declarations, and follow the standard of declaring each variable on its own line... and initialise-as-you-declare each variable, which has the side-effect of moving each variable "down" into it's smallest-possible-scope; This is generally regarded as a "good thing", because it minimises opportunity for a variable to be accidentally used/modified somewhere-else unintentionally. This goes TRIPLE for "temporary" variables!!!

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

"PROOF" that float ?ALLWAYS? widens to an EQUIVALENT double

“证明”浮动?总是?扩大到一个等效的两倍

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: None, as expected.

IE:没有,正如预期的那样。