I use the following function to filter a signal. The code works perfectly for order 4, but when I use a higher order, like 5, I get NaN values in the output. Your help is highlly appreciated
void filt(int ord, double a[], double b[], int np, double x[], ArrayList<Double> array)
{
int i,j;
// y[0]=b[0]*x[0];
array.add(0, b[0]*x[0]);
for (i=1;i<ord+1;i++)
{
array.add(i, 0.0);
for (j=0;j<i+1;j++)
array.add(i, array.get(i)+b[j]*x[i-j]);
for (j=0;j<i;j++)
array.add(i, array.get(i)-a[j+1]*array.get(i-j-1));
}
for (i=ord+1;i<np;i++)
{
array.add(i, 0.0);
for (j=0;j<ord+1;j++)
array.add(i, array.get(i)+b[j]*x[i-j]);
for (j=0;j<ord;j++)
array.add(i, array.get(i)-a[j+1]*array.get(i-j-1));
}
}
I tried the same functionality of Matlab, and got NaN values. I dig in Matlab documentation and found the following which explains the NaN values:
"For higher order filters (possibly starting as low as order 8), numerical problems due to roundoff errors may occur when forming the transfer function using the [b,a] syntax."
Therefor the butterworth filter is unstable for higher orders.
To get over this problem in Matlab, try the following:
n = 6; Wn = [2.5e6 29e6]/500e6;
ftype = 'bandpass';
% Transfer Function design
[b,a] = butter(n,Wn,ftype);
h1=dfilt.df2(b,a); % This is an unstable filter.
% Zero-Pole-Gain design
[z, p, k] = butter(n,Wn,ftype);
[sos,g]=zp2sos(z,p,k);
h2=dfilt.df2sos(sos,g);
% Plot and compare the results
hfvt=fvtool(h1,h2,'FrequencyScale','log');
legend(hfvt,'TF Design','ZPK Design')
Related
When the user change the locale in device the numbers are also getting changed according to the selected locale. This is causing NumberFormatException while performing mathematical operations and app is getting crashed. The code snippet which is causing the crash is given below.
public static double ToDataUnitMB(double _dataBytes){
double dDataBytes;
dDataBytes = Double.parseDouble(getDecimalFormat().format(_dataBytes / 1048576));
return dDataBytes; }
This code snippet is causing NumberFormatException and the value in _dataBytes is shown as "७२.४१". Can anyone help me to prevent the number from changing when user change the locale.
Update
I am getting the value "७२.४१" after performing the below operation getDecimalFormat().format(_dataBytes / 1048576)
So while parsing to Double it is showing numberFormatException
Since you're starting with raw _dataBytes you have several options how to format number independent of the locale.
First Approach:
You can modify following snippet to your needs. It will give you the same output regardless of the user locale.
String patern = "###.##"; //your pattern as per need
Locale locale = new Locale("en", "US");
DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getNumberInstance(locale);
decimalFormat.applyPattern(patern);
double formatedDouble = Double.parseDouble(decimalFormat.format(_dataBytes/(1024*1024f)));
Keep in mind that this method also makes grouping and decimal separators to be fixed, so that comma and dot will alway be used as, respectively, grouping separator and decimal separator.
Second Approach:
If you do not strictly require Double you could generate formatted String with something similar to following method:
String generateFormatedFileSize(long _dataBytes) {
String formatedFileSize = "";
long bytes = _dataBytes;
short unit = 1024;
if (bytes < unit)
formatedFileSize = bytes + " B";
else {
int exp = (int) (Math.log(bytes) / Math.log(unit));
formatedFileSize = String.format("%.1f %sB", bytes / Math.pow(unit, exp), "KMGT".charAt(exp - 1));
}
return formatedFileSize;
}
This formatting will be sensitive to grouping separator and decimal separator, but otherwise insensitive to Locale.
For Local that uses "US" numbering format, this will give you following output:
12.5 KB
5.3 B
8.0 MB
And for Local using "European" numbering format:
12,5 KB
5,3 B
8,0 MB
Off course, these two methods are not exclusive and you could use some mix of these approaches at different parts of the App.
I using this code for get wifi signal set.(BSSID, SSID, RSSI.. etc.).
public void sortScanResult()
{
wifiScan.scanWifiSignal();
scanedResults = new ArrayList<ScanResult>(wifiScan.getScanResults());
Comparator<ScanResult> comparator = new Comparator<ScanResult>() {
#Override
public int compare(ScanResult lhs, ScanResult rhs) {
return (lhs.level > rhs.level ? -1 : (lhs.level == rhs.level ? 0 : 1));
}
};
Collections.sort(scanedResults, comparator); //sorting result
if (scanedResults.size() > 10) {
int resultSize = scanedResults.size();
for (int index = resultSize - 1; ; index--) {
scanedResults.remove(index);
if (scanedResults.size() == 10) break;
}
}
}
but the scanResults of this code return RSSI level by INT.
I want get rssi level value by float for precision because I use for indoor navigation.(Finger Print).
Is there no way to get RSSI level value by float?
ps. sorry, I'm poor at English.
Even if it were in float, that doesn't imply greater accuracy as float is 32bit same as int.
But anyway it's just not available at the hardware level:
Vendors and chipset makers provide their own accuracy, granularity.
Cisco Systems cards have a RSSI_Max value of 100 and will report 101 different power levels, where the RSSI value is 0 to 100. Another popular Wi-Fi chipset is made by Atheros. An Atheros based card will return an RSSI value of 0 to 127 (0x7f) with 128 (0x80) indicating an invalid value.
So that's what you have to work with, around 7 bits.
P.S. you won't have much luck with your approach according to the wiki article:
RSSI doesn't always provide measurements that are sufficiently accurate to properly determine the location.
I'm developing an app where I use the Geocoder to get a place's coordinates.
The operative is this:
The user defines an address.
The geocoder finds that address and I get the coordinates from that address.
This coordinates are in decimal format and I need them in degrees-minutos so I format them.
To format the coordinates from decimal to degrees-minutes I use:
String frmtLatitude = Location.convert(Double.parseDouble(lat), Location.FORMAT_MINUTES);
So, if I have for example this latitude 43.249591 in decimal value, it returns it like this 43:14.97546.
After this, I have to make some operations to finally get the latitude with this appearance: 4314.975
When I do this operations, one of them is to split the value using the ".". I split 14.97546 to get in one hand the 14 and in the other 97546.
Until here, everything ok. It works fine when I have my phone's language selected to be in english. But if I select to be in spanish, the app crashes. I have followed the stacktrace and it points there. Is like that in english when using the first commented function to convert from decimal to degrees-minutes it separates the decimals with a "." but if I have it in spanish, it separates them with a ",".
Can this really happen or the cause could be another thing?
We can look at the source code of the convert method
public static String convert(double coordinate, int outputType) {
if (coordinate < -180.0 || coordinate > 180.0 ||
Double.isNaN(coordinate)) {
throw new IllegalArgumentException("coordinate=" + coordinate);
}
if ((outputType != FORMAT_DEGREES) &&
(outputType != FORMAT_MINUTES) &&
(outputType != FORMAT_SECONDS)) {
throw new IllegalArgumentException("outputType=" + outputType);
}
StringBuilder sb = new StringBuilder();
// Handle negative values
if (coordinate < 0) {
sb.append('-');
coordinate = -coordinate;
}
DecimalFormat df = new DecimalFormat("###.#####");
if (outputType == FORMAT_MINUTES || outputType == FORMAT_SECONDS) {
int degrees = (int) Math.floor(coordinate);
sb.append(degrees);
sb.append(':');
coordinate -= degrees;
coordinate *= 60.0;
if (outputType == FORMAT_SECONDS) {
int minutes = (int) Math.floor(coordinate);
sb.append(minutes);
sb.append(':');
coordinate -= minutes;
coordinate *= 60.0;
}
}
sb.append(df.format(coordinate));
return sb.toString();
}
We can see that it uses a DecimalFormat with a given pattern. So, if we look to the DecimalFormat constructor :
public DecimalFormat(String pattern) {
// Always applyPattern after the symbols are set
this.symbols = new DecimalFormatSymbols(Locale.getDefault());
applyPattern(pattern, false);
}
We can see here that even if we give a pattern, it uses the locale values. The javadoc also said :
Parameters:
pattern A non-localized pattern string.
To finish, we can go here to see the different local variant of numbers representation : http://docs.oracle.com/cd/E19455-01/806-0169/overview-9/index.html
So we can see that US-English use the "dot format" and that Spanish use "comma format".
To answer your question : the proflem you're facing is probably due to the Decimal format of your locale. I advice you to be REALLY CAREFUL when converting types of objects to make manipulation on them. Converting an int to a String should be only to display it.
I think you should seperate decimal part of your number when it stills a float (or any decimal type) and then convert your object to a String to display it. You can take a look at Math class or search SO to get some example on how to this ;)
Also, as #Dmitry said, you can get DecimalSeparator with DecimalFormatSymbols.getDecimalSeparator().
Sources
Location.convert(double,int) source code
DecimalFormat(String) source code
Java "Decimal and thousands separators"
You are right, decimal seperator depends on your locale. You can get it by something like this
DecimalFormat df = new DecimalFormat();
DecimalFormatSymbols formatSymbols = df.getDecimalFormatSymbols();
char separator = formatSymbols.getDecimalSeparator();
I have a 10-field average lap calculator. However, in testing, someone said they normally only run X laps in practice, vs. 10 (let's say 7).
I think I could use an if statement, but there'd be at least 10 of them and a bunch of clumsy code, and I'm not sure on arrays/switch statements exactly. I think all of those might be possible, but my low level of experience has yet to fully comprehend these useful tools.
CURRENT CODE:
double tenLapAvgVar = ((lap1Var + lap2Var + lap3Var + lap4Var + lap5Var + lap6Var + lap7Var + lap8Var + lap9Var + lap10Var) / 10);
So essentially, if someone leaves a field or fields blank, I want to calculate the average based on the populated fields, not 10 (if they leave 3 fields blank, calculate based on 7, for instance). Any help you guys could provide would be much appreciated, thanks!
You could have an ArrayList<EditText> object and a method which iterates over it and adds up the values. Something like:
public double getLapAverage()
{
int noOfCompletedLaps = 0;
double lapAve = 0;
double lapsTotal = 0;
for(EditText text : textBoxes)
{
if(text.getText().toString().length() > 0)
{
//psuedo code, and assuming text is numerical
lapsTotal += Double.parse(text.getText().toString());
noOfCompletedLaps++;
}
}
if( noOfCompletedLaps > 0)
{
lapAve = lapsTotal / noOfCompletedLaps;
}
return lapAve;
}
Maybe it would be better if you used an array instead of 10 different variables.
Then you can use a for statement and initialize them to 0, afterwords let the user fill the array and count how many are not zero.
Finally sum up all the array and divide by the count you previously calculated.
This is a performance critical part of my android application, and I am using the NDK (c) to process a large bitmap array.
int blender(const char* blendMode, int c1, int c2, int amount){
int sob, sog, sor, soa, dsr, dsg, dsb, dsa = 0;
dsr = Argb_GetRed(c1);
dsg = Argb_GetGreen(c1);
dsb = Argb_GetBlue(c1);
dsa = Argb_GetAlpha(c1);
sor = Argb_GetRed(c2);
sog = Argb_GetGreen(c2);
sob = Argb_GetBlue(c2);
soa = Argb_GetAlpha(c2);
int src_alpha, mix_alpha, dst_alpha;
src_alpha = soa * ((255 * amount) / 100) >> 8;
if (!strcmp(blendMode, "normal")) {
PSD_BLEND_NORMAL(dsr, sor, mix_alpha);
PSD_BLEND_NORMAL(dsg, sog, mix_alpha);
PSD_BLEND_NORMAL(dsb, sob, mix_alpha);
}
else if (!strcmp(blendMode, "exclusion")) {
mix_alpha = soa / 255;
//.... it's not always just the 3 macros
PSD_BLEND_EXCLUSION(dsr, sor, mix_alpha);
PSD_BLEND_EXCLUSION(dsg, sog, mix_alpha);
PSD_BLEND_EXCLUSION(dsb, sob, mix_alpha);
}
~~~~~~~~~ X 20 or so blend modes ~~~~~~~~~~~~
}
Currently it's running this blender function on every pixel, and doing a switch (clearly inefficient)
also, it has to take the original command as a string (From json, and passed down through java)
I can think of a couple ways to make it more efficient, but they all involve writing 2 giant switch statements. I would prefer to use 1 switch statement, or lookup if possible
Thank you!
Pretty nasty problem but I got a "hackish" idea.
If the 'blendMode' names are chosen nicely, you could compare only the first two (or three) letters of the strings. If there are multiple strings with same first letters, you could make a special case and compare first and third letter and so on.
This trick would make the code a lot faster than calling strcmp() all the time. Also inlining the compare function might help too.
Here is some code:
/* compares first two letters of the string */
inline int fast_cmp(const char *mode, const char *cmp) {
return (mode[0] == cmp[0] && mode[1] == cmp[1]) ? 1 : 0;
}
if( fast_cmp(blendMode, "no") ); /* for "normal" */
if( fast_cmp(blendMode, "ex") ); /* for "exclusion" */
In action: http://ideone.com/OiXS0
Ofcourse the comparisons could be written directly into if / else statements but it might get confusing. This can be fixed with small and nifty macro:
#define FAST_CMP(x, y) x[0] == y[0] && x[1] == y[1]
And here is the macro in action: http://ideone.com/NQFwW
This macro version is perhaps the fastest way to do the comparison.