How to convert fraction into floating point number in Android? - android

Hello I have a really simple qestion, in my app I have an EditText and what I would like for instance is this:
If I write 1/2 I would like 0.5 in the field.
How can I do this?

only add any dight/any other digit or any text with this fraction?
need info
Why you "dont want to split the string and then covert to individual strings to numbers and then divide them to have result"?
I am not aware of any built-in function to do that so the simplest solution:
double parse(String ratio) {
if (ratio.contains("/")) {
String[] rat = ratio.split("/");
return Double.parseDouble(rat[0]) / Double.parseDouble(rat[1]);
} else {
return Double.parseDouble(ratio);
}
}
It also covers the case where you have integer representation of ratio
parse("1/2") => 0.5
parse("3/7") => 0.42857142857142855
parse("1") => 1.0

Related

Android: how to conditionally show floating point part in string resource?

Is it possible to show the floating point part in a string resource if it exists and hide it if it doesn't?
So, if this is my string resource:
<string name="liter">%.1f liter</string>
This will always show the floating point part:
getString(R.string.liter, 1.0) // 1.0 liter (I need this to be "1 liter", without the .0 part)
getString(R.string.liter, 1.5) // 1.5 liter
Can this be achieved?
As per your requirement, you can simply achieve this by typecasting. remove the template from string resources.
fun getLiterString(value : Float) : String
{
if(value.toInt().toFloat() == value)
{
return getString(R.string.liter_d, value.toInt())
}
else
{
return getString(R.string.liter_f, value)
}
}
string.xml
<string name="liter_d">%d liter</string>
<string name="liter_f">%.1f liter</string>
If you want to keep string resources,
You can make two templates for liter or else you have to replace ".0" from the output.
Example : https://pl.kotl.in/3poIS2lLJ

Prevent numbers from changing according to the locale in android

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.

Is language conditional in some operations?

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

Making a calculator but no way to retrieve functions

An easy way to make an android calculator would be to have 3 separate edit text boxes and have the user in put a number, a function, and then another number like 3 + 3. This would make it easier for the app dev to store the number(s) and function(s) and perform a calculation.
Now... my calculator app has the ability to out put all the input real-time, the down side is that when I retrieve what's in the input box, i retrieve it as string (to make sure i include all the functions input-ed). I know how to retrieve numbers (by using int parse) but how do I retrieve the functions such as + - / * ? (They're the main bit!! :O). Any help would me much appreciated thanks :)
Try to use a switch that analyze and identify the correct operation. Something like this:
(I suppose the content of function EditText in a string named functionSign
...
switch(functionSign)
{
case "+": return op1+op2;
case "-": return op1-op2;
...
EDIT 2:
I suppose that user can put only the functions simbols + - / * and the operations are organized in a method:
public double calculate()
{
String operations= inputEditText.getText().toString();
StringTokenizer st= new StringTokenizer(operations);
//to calculate in input must have at last one operation and two operands
//the first token must be a number (the operation scheme is (number)(function)(numeber)...)
double result=Double.parseDouble(st.nextToken());
while(st.hasMoreTokens())
{
String s=st.nextToken();
if(s.equals("+"))
result += Double.parseDouble(st.nextToken());
else if(s.equals("-"))
result -= Double.parseDouble(st.nextToken());
else if(s.equals("*"))
result *= Double.parseDouble(st.nextToken());
else if(s.equals("/"))
result /= Double.parseDouble(st.nextToken());
else
throw new Exception();
}
return result;
}
This code is a really simple example, you must be sure that the user don't try to calculate something incomplete like:
3 + 3 -
/ 3 * 5
and similar. What the user should be able to do is your decision
You can get the operator as a string and use if statements to determine what to do:
String operator=operatorEditText.getText().toString();
if (operator.equals("+")){
//addition code here
}
else if (operator.equals("-")){
//subtraction code here
}
...

Detecting only the last two digits in text entry box for a calculator app

I'm still pretty new to this, but I'm trying to make a calculator for myself to use at work; similar to a resistor calculator.
I am hope to change a textview and imageview according to the last two digits entered into a edittext box. For example, if I were to type in "9,000,011", I would want to display a certain color of image and text that corresponds with "11" and the same color and text for say 1,000,011. Also different for 12, 13, and so on. this way No matter what number I type it only looks at the last two digits. Does anyone know the way to do this or maybe can just point me in the right direction?
here is how I'm
private void calculate() {
number = Double.parseDouble(inputnumber.getText().toString());
ImageView iv = (ImageView) this.findViewById(R.id.pairimage);
if (number == 6000001) {
iv.setImageResource(R.drawable.white);
txtnumber.setText("White");
} else if (number == 6000002) {
iv.setImageResource(R.drawable.red);
txtnumber.setText("Red");
}
//*and so on, all the way up to 99*
}
If you want just the last two, then I would use
String wholeNumber = inputnumber.getText().toString();
int n = Integer.valueOf(wholeNumber.subString(wholeNumber.length()-2, wholeNumber.length()-1);
and then a switch block:
switch(n) {
case 1:
iv.setImageResource(R.drawable.white);
txtnumber.setText("White");
break;
case 2:
iv.setImageResource(R.drawable.red);
txtnumber.setText("Red");
break;
}
etc.
Maybe convert the number to a String and then look at that e.g.
String theNumber = String.valueOf(number);
String lastTwoDigits =
theNumber.substring(theNumber.length() -2, theNumber.length());
Then you can have your if statements to read the lastTwoDigits. Or convert back to int (Integer.valueOf(lastTwoDigits); and use a switch statement. Or put the values 0-99 into a Map and have a Command object or something as the value which gets executed.
Obviously you'll need some validation here on the user input.
You have a couple of options. The easiest one is to use the modulus operator like:
number = number % 100;
switch (number) {
case 1:
// do stuff;
break;
case 2:
// do stuff;
break;
}
For this to work, though, "number" will have to be an integer. It's an integer in your examples, so that may work for you; otherwise you can try some math tricks like:
int number2 = (int)(number * 100) % 100;
Go with the sub-string approach. I've found that some number combinations don't multiply/divide well in java.

Categories

Resources