Dealing the measurement units - android

Every country uses own measurement units, for example people in US measure temperature in F however Canada and most European countries in C. Same is applied for measurement weight, distance and so on.
I define measurement units in my application as
<string-array name="measure_units">
<item>lb</item>
<item>oz</item>
<item>cwt</item>
<item>ft</item>
<item>yd</item>
for default locale and then for France I define something like
<string-array name="measure_units">
<item>kg</item>
<item>ml</item>
<item>tn</item>
<item>dm</item>
<item>m</item>
So far so good, however it is a huge work to define the values for every country considering tons of duplicates. So I am thinking to introduce 2-4 basic measurement systems and specify values only for them, but how to implement it for Android? Is there any measurement systems mapping embedded in the OS? If there is no such functionality how do you deal with the problem?

SO this kind of thing is part of localization of an app. Generally the rule is- use one system internally in your app (generally metric, but anything will work). Convert to local units only right before display or right after data is input, never store data in anything but your internal format.
You might be able to find a library to do this for you, but its not built into Android or Java. Typically though you don't map every language to a length, temperature, etc. You do just what you suggested- build a couple of linked choices, and map Locales to a specific set of choices. If you pick metric as your default, you only need to do overrides for 2 or 3 countries- pretty much everyone uses metric.

I have a suggestion.
First store the values in international units. (Distance in m, Weight in kg, Temperature in C . . . etc). Then use some methods to convert international units to other units. When ever you need non-international units, use those methods to get the converted values. You can use an if statement or a switch to get the values accordingly.
As an example
if(/*international unit ?*/){
Log.D("International unit : ", temperature + "C");
}else{
Log.D("Non - International unit : ", getTemperatureInFahrenheit(temperature) + "F");
}
float getTemperatureInFahrenheit(float celsius){
return ((celsius * 9 / 5.0) + 32)
}

Related

How to properly support different units in Room Database?

I am using Room Database in my Android App. One of the columns represents volume of drink in milliliters [ml]. I wonder what is the proper way of giving user option to choose/change units to [cl] or other.
Should I make a settings option to choose unit, and then convert all values in my database?
Should I store for example [ml] and then convert values depending on units selected by user?
What is the most efficient way? What will be less resources consuming?
Are You guys having some good open source examples/tutorials/code snippets?
It really depends on the volume and complexity of your conversions.
If you only have a single value (ML) and need to convert it to another value (CL, OZ...) then you can just set a base unit to the DB and convert the value in real time just before displaying them to the user.
If you feel this will get out of hand since you'll have many value types and you'll have a problem keeping track on all of them you can do the conversion in the DB that will cause some overhead on the select queries.
for example, you have this table:
ID unit val
--- --- ---
1 ML 960
2 ML 4112
3 KG 70
4 KG 35
5 C 37
You'll always keep base units in the DB the same meaning you will not mix them with F, OZ and LBS.
You can convert the units in your select query:
SELECT id, unit, val,
case when unit = 'ML' then val * 0.033
when unit = 'KG' then val / 2.205
when unit = 'C' then val * 9/5 + 32
end as result
FROM tbl
In both cases, since this is an Android app the work will be done via SQLite or the app itself.
Personally, I would not mix units on the same table because it would add a layer of complexity to later sort, compare and retrieve them.
Hope that helped.

Math.sin() does not give accurate results [I'm using Math.toRadians to pass the right values]

I'm actually using Math.sin() in my android app to calculate a sinus of a given angle (using Math.toRadians(angle_in_degrees)). For exemple when I want to get the Math.cos(90) which is 0, the result is 6.123233... E-17. Thanks you.
For floating point numbers, the system can often only approximate their values. For instance, the system would return something like 0.333333 for the expression (1.0 / 3). The number of 3s after the decimal point will be different depending on whether you're a floats or doubles, but it will still be limited to some finite length.
If you're just displaying the value, then you can limit the number of digits using something like String.format("%0.2f", value) or by rounding it using one of the rounding functions such as Math.round().
The tricky part comes when you need to compare the value to something. You can't just use if (value == some_constant) or even if (value == some_variable). At minimum, you usually have to use something like if (Math.abs(value - some_constant) < 0.001). The actual value of the '0.001' depends on the needs of your particular application and is customarily defined as a named constant.
For more complicated needs, you can implement the algorithm in the Floating-Point Guide.
You're getting back an approximation from Math.cos(Math.toRadians(90)) which is
6.123233... E-17 == 0.00000000000000006123233... which is basically 0
The following link should help clear things up as far as the precision of doubles/floats in programming.
http://www.java67.com/2015/09/float-and-double-value-comparison-in-java-use-relational.html

Hi I want to know what is the appropriate process of converting Amplitude to dB . Through Android device

I want to know what is the appropriate process of converting Amplitude to dB. I am using double as below
db = (20 * Math.log10(mediaRecorder.getMaximimAmplitude));
But there are suggestions to use double as below
db = (20 * Math.log10(x2 / REFERENCE));
I dont know what reference is to use in which scenerio
The decibel is a much misused unit. It is defined as the 10 log (P1/P2) where P1 is the measured power, and P2 is the reference power. That is, it is always relative to some reference power. A common reference power is one milliwatt, and this is the definition of dBm. 0dBm is one milliwatt; +30dbm is one watt. Don't be misled by the oft-quoted "0dBm = one milliwatt in 600 ohms". This is an artifact of when voltage measuring devices were used to display dBm. Because they were voltage measuring rather than power measuring, an impedance at which they read correctly needed to be specified, and it was nearly always 600 ohms.
Over the years dB usage has been stretched to cover situations where having a logarithmic unit is really useful. For instance the voltage gain of an amplifier may be quoted in dB, using the formula 20log(Vout/Vin). In this situation, the input and output impedances (and hence powers) are often vastly different, so the usage is technically wrong. In practice it is a convenient unit to work with, and has been given some legitimacy by labeling it dBv.
The first formula you are using will return dB referenced to 1 volt in whatever impedance your circuit exhibits. This is fine, but it won't be dBm. Often this does not matter, as you just need to graph gain in dB against an arbitrary reference.If you need it to be dBm just find the circuit impedance and use Ohms law to work out what voltage represents one milliwatt in that impedance.
The second formula is a bit strange. What is x2? I would expect the formula to be 20log(Vmeasured/Vreference).

How to revert back from currency format, Android?

I'm developing Android app which uses this method:
public static String currencyFormat(BigDecimal n) {
return NumberFormat.getCurrencyInstance().format(n);
}
which formats number based on Locale currency.
How to revert back from currency format, e.g. $35, to 35? Note that I cannot just remove First character because different locales have different currency name lengths.
You must store the currency unit in a separate field, encapsulated into some higher-order abstraction such as a final value class (with appropriate equals and hashcode defined), eg called CurrencyAmount. [if you do scala, basically you want a case class]. Any other solution will require you to 'reverse engineer' the unit portion from the amount portion and depending on the complexity of your spec of allowable values, it might be reliable only to various degrees. I would just encode the two portions in their own fields and solve this for all cases.
You might try to cut out all non numeric characters from a String with a regex.
Try this.

Doing order by using the Jaro-Winkler distance algorithm?

I am wondering how would I be able to run a SQLite order by in this manner
select * from contacts order by jarowinkler(contacts.name,'john smith');
I know Android has a bottleneck with user defined functions, do I have an alternative?
Step #1: Do the query minus the ORDER BY portion
Step #2: Create a CursorWrapper that wraps your Cursor, calculates the Jaro-Winkler distance for each position, sorts the positions, then uses the sorted positions when overriding all methods that require a position (e.g., moveToPosition(), moveToNext()).
Pre calculate string lengths and add them into separate column. Then sort entired table by that that length. Add indexes (if you can). Then add extra filters for example you don't want to compare "Srivastava Brahmaputra" to "John Smith". The length are out of wack by way too much so exclude these kind of comparison by length as a percentage of the total length. So if your word is 10 characters compare it only to words with 10+-2 or 10+-3 characters.
This way you will significantly reduce the number of times this algorithm needs to run.
Typically in the vocalbulary of 100 000 entries such filters reduce the number of comparisons to about 300. Unless you are doing a full blown record linkage and then I would wonder why use Android for that. You would still need to apply probabilistic methods for that and calculate scores and this is not a job for Android (at least not for now).
Also in MS SQL Server Jaro Winkler string distance wrapped into CLR function perform much better, since SQL Server doesn't supprt arays natively and much of the processing is around arrays. So implementation in T-SQL add too much overhead, but SQL-CLR works extremely fast.

Categories

Resources