安卓的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,所以如果答案很明显或者我的语法很奇怪,请耐心等待。希望有人能解决这个问题
# 1 楼答案
可能想尝试
Double.parseDouble(new String(tmpr[i]))
而不是隐式强制转换:这应该不会有什么不同,但我见过类似于浮动的奇怪事情# 2 楼答案
@digiphd
这不是答案我谦虚地试图证明,Java环境将浮点转换扩展到双精度,或将双精度转换缩小到浮点,都没有错
请在您的环境中运行此测试(或等效测试)好吗
除此之外,我唯一能建议的就是仔细检查变量声明,并遵循在自己的行中声明每个变量的标准。。。并在声明每个变量时进行初始化,这样做的副作用是将每个变量“向下”移动到其可能的最小范围内;这通常被认为是一件“好事”,因为它最大限度地减少了在其他地方意外使用/修改变量的机会。这是“临时”变量的三倍
“证据”是浮动的吗?总是这样吗?扩大到相等的两倍
输出
IE:没有,正如预期的那样
# 3 楼答案
我想你会发现问题在于这句话:
我认为您只是实例化了一个数组,如果您将其替换为:
通过创建一些独立的对象,你会发现tmpi和img是匹配的