How to parse string to get double value from it - java

Help me please for the next problem:
There is String pattern, assume it's public final static variable. There is string where we search. There is class, simple wrapper to double
public class Wrapper {
private double value;
public double getValue() {
return value;
}
public Wrapper(double value) {
this.value = value;
}
}
I need method
public Wrapper parse(String s, int index)
which returns Wrapper's object if string at the index is double number with maximum 2 digits after decimal point(if there is decimal point at all) and right after number ends there is String pattern after it
For example for strings
String pattern = "money";
String search = "Giveme10.25moneyplease";
parse(search, 6) returns new Wrapper(10.25)
In other cases (index less then zero, greater then length of the string, substring that starts from index isn't number at all or it's double number but it contains more then 2 digits after decimal point or there is no string pattern after number) method must return null
And another method that differs only string pattern must be first and then double number with maximum 2 digits after decimal point and all other the same
String pattern = "money"
String s = "Ihavemoney10.50"
parse1(s, 5) returns new Wrapper(10.50)

You can use DecimalFormat along with ParsePosition like this
import java.text.DecimalFormat;
import java.text.ParsePosition;
public class TestP {
public static void main(String[] args) {
DecimalFormat decimalFormat = new DecimalFormat("00.##'money'");
String search = "Giveme10.25moneyplease";
int index = 6;
//output 10.25
Number number = decimalFormat.parse(search, new ParsePosition(index));
if (number != null) {
String s = number.toString();
if (s.contains(".") && s.length() > 5) {
number = null;
}
}
System.out.println(number);
}
}

Related

Writing a program for a running competition using array

Write a program that asks for the names of three runners and the time, in minutes, it took each of them to finish a race. The program should display the names of the runners in the order that they finished.
The program works for whole numbers but is unable to arrange decimals. If I change the variable to integers, the input causes an error. Is there a solution for this?
import java.util.Arrays;
import java.util.Scanner;
class Runners implements Comparable<Runners> {
public String name;
public double time;
public Runners(String name, double time) {
this.name = name;
this.time = time;
}
public String toString() {
return String.format(" %s: %.2f minute(s) ", name, time);
}
public int compareTo(Runners other) {
return (int) (this.time - other.time);
}
}
public class Question2 {
public static void main(String[] args) {
int count = 3;
Runners[] runnersData = new Runners[count];
Scanner input = new Scanner(System.in);
for (int i = 0; i < count; i++) {
System.out.println("Enter runner's name and time taken in minutes: ");
runnersData[i] = new Runners(input.next().strip(), input.nextDouble());
}
input.close();
Arrays.sort(runnersData);
System.out.println(Arrays.toString(runnersData));
}
}
The unsorted decimals:
The error if changed to int:
compareTo doesn't require you to return the results of your arithmetic. You only have to return an integer signifying whether the items are equal, greater or less than.
public int compareTo(Runners other) {
if(this.time == other.time)
return 0;
else if(this.time > other.time)
return 1;
else
return -1;
}
See the documentation on compareTo here. Also be aware that comparing doubles won't always behave the way you expect. I added the above for an example usage, but you can probably just return Double.compareTo(d1, d2). See those docs.

How to shorten (format) String output properly?

Simple questions as a beginner making big problems.
I want to shorten (format) a String to only show 1 decimal or 2. Unlucky it is a String not a double.
String getNumber = "6.000m";
I know there is a printf() function but as far I learned it is to print multiple string in a proper order.
How can I make the output to be with only one decimal or if it has more numbers which aren't 0?
6.000 m --> 6.0
4.900 m --> 4.9
4.750 m --> 4.75
I assume it is always "m" at the end with some optional whitespace in front of it. So I remove it first using a regex.
DecimalFormat is your friend to do the rest:
import java.text.DecimalFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Ff {
static Pattern numberPart=Pattern.compile("([0-9.]*)\\b*m");
static DecimalFormat df=new DecimalFormat("0.0#####");
public static String format(String input)
{
Matcher m=numberPart.matcher(input);
if(m.matches())
{
return df.format(Double.parseDouble(m.group(1)));
}
return null;
}
public static void main(String args[]) {
System.out.println(format("6.000m"));
System.out.println(format("4.900m"));
System.out.println(format("4.750m"));
}
}
and the output is:
6.0
4.9
4.75
You shouldn't use regex, because it is very hard to maintain.
As an example:
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-
\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")#(?:
(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-
5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|
[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\
[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
This is a part of some code to validate an email with a regex. Regexes were necessary back then when computers were slow, because regexes are fast. Nowadays you don't need them anymore and maintenance is key.
After using the test cases:
0.000 m -> 0.0
1.000 m -> 1.0
9.000 m -> 9.0
1.100 m -> 1.1
1.900 m -> 1.9
1.110 m -> 1.11
1.010 m -> 1.01
1.111 m -> 1.111
1.101 m -> 1.101
1.101m -> 1.101
I've come to this conclusion:
shortenGivenNumber(String wholeNumber); will be the Method you'll use to shorten your number. The other methods are there to make the main method more readable.
public class NumberShortener {
public String shortenGivenNumber(String wholeNumber) {
int endOfShortNumber = findEndOfNumber(wholeNumber);
String shortenedNumber = cutOutNumber(wholeNumber, endOfShortNumber);
return shortenedNumber;
}
private int findEndOfNumber(String numberWithZeroesAndM) {
int lastZero = findIndexOfZeroAfterNumber(numberWithZeroesAndM);
int endOfNumber = lastZero;
endOfNumber = handleNo0AtEndCase(numberWithZeroesAndM, lastZero, endOfNumber);
return endOfNumber;
}
private int findIndexOfZeroAfterNumber(String wholeNumber) {
int lastZero;
int searchIndex = 3;
boolean numberAfterZero;
do {
numberAfterZero = false;
lastZero = findNextIndexOfZero(wholeNumber, searchIndex);
numberAfterZero = isANumberAfterThisZero(wholeNumber, lastZero);
searchIndex++;
}while(numberAfterZero == true && valueExistsAtEnd(lastZero));
return lastZero;
}
private int findNextIndexOfZero(String wholeNumber, int searchIndex) {
return wholeNumber.indexOf("0", searchIndex);
}
private boolean isANumberAfterThisZero(String wholeNumber, int lastZero) {
boolean numberAfterZero = false;
for(int i = 1; i < 10; i++){
char characterAfterZero = getCharacterAfterZero(wholeNumber, lastZero);
char iAsChar = convertIntToChar(i);
if(isTheCharacterThisNumber(characterAfterZero, iAsChar)){
numberAfterZero = true;
}
}
return numberAfterZero;
}
private boolean valueExistsAtEnd(int lastZero) {
return lastZero != -1;
}
private int handleNo0AtEndCase(String wholeNumber, int lastZero, int endOfNumber) {
if(thisSignIsntAtEnd(lastZero)){
int indexOfSpace = getIndexOfSpace(wholeNumber);
endOfNumber = indexOfSpace;
endOfNumber = handleNoSpaceAtEndCase(wholeNumber, endOfNumber, indexOfSpace);
}
return endOfNumber;
}
private int getIndexOfSpace(String wholeNumber) {
return wholeNumber.indexOf(" ");
}
private int handleNoSpaceAtEndCase(String wholeNumber, int endOfNumber, int space) {
if(thisSignIsntAtEnd(space)) {
int indexOfM = getIndexOfM(wholeNumber);
endOfNumber = indexOfM;
}
return endOfNumber;
}
private int getIndexOfM(String wholeNumber) {
return wholeNumber.indexOf("m");
}
private char getCharacterAfterZero(String wholeNumber, int indexOfZero) {
int indexAfterZero = indexOfZero+1;
return wholeNumber.charAt(indexAfterZero);
}
private char convertIntToChar(int i) {
return (char) (i+48);
}
private String cutOutNumber(String wholeNumber, int endOfNumber) {
return wholeNumber.substring(0, endOfNumber);
}
private boolean isTheCharacterThisNumber(char characterAfterZero, char iAsChar) {
return characterAfterZero == iAsChar;
}
}
It always copies the first 3 characters(x.x). The first 0 (after the x.x), without any number following, will be used as the last index which indicates the end of the final number substring. If there are numbers over 0 until the end, it will use the space (1.123 m). If there isn't a space, it will use the m (1.123m).

Negative int to hexadecimal conversion

I am converting some integers to hexadecimals but the problem i have is when i pass a negative value to convert it to hex.
Example:
String satpos = "13.0";
String satposs=satpos.replaceAll("\\.", "");
int satposition = Integer.parseInt(satposs);
String nids = Integer.toHexString(satposition);
String finished = nids+"0000";
Application returns "820000" in this case and that is the correct value i need.
But if i pass:
String satpos = "-7.0";
String satposs=satpos.replaceAll("\\.", "");
int satposition = Integer.parseInt(satposs);
String nids = Integer.toHexString(satposition);
String finished = nids+"0000";
Application returns "ffffffba0000" but i should get "DCA0000"
Any help is appreciated.
Based on a comment by Andreas, here is a test program that prints the values you want:
public class Test {
public static void main(String[] args) {
convert("13.0");
convert("-7.0");
}
private static void convert(String satpos) {
String satposs = satpos.replaceAll("\\.", "");
int satposition = Integer.parseInt(satposs);
if (satposition < 0) {
satposition += 3600;
}
String nids = Integer.toHexString(satposition);
String finished = nids + "0000";
System.out.println(finished);
}
}
If the angle is negative, add 3600 because the angle is in tenths of a degree.

Convert double to string and remove euro sign currency

I am trying to format double values to currency and then remove the euro sign but my application crashed. can someone tell me where am wrong please?
public class Formatting {
public static String replaceString(String text){
NumberFormat formatter = NumberFormat.getCurrencyInstance();
String moneyString = formatter.format(text);
System.out.println("epargne: "+moneyString);
return text.replaceAll("£", "");
}
public static String convert(double x){
return replaceString(Double.toString(x));
}
}
i called it as follows in class y
double x = a + b + c;
System.out.println(Formatting.convert(x));
format accepts a double, no need to convert that value to a String. replaceAll requires a regexp, you can just simply use replace which requires a single char.
public static String replaceString(double value){
NumberFormat formatter = NumberFormat.getCurrencyInstance();
String currencySymbol = formatter.getCurrency().getSymbol();
String moneyString = formatter.format(value);
return moneyString.replace(currencySymbol, "");
}
public static String convert(double x){
return replaceString(x);
}
As you don't want to get currency returned, you could simply use DecimalFormat which will also give you rounding to 2 decimal places (from your comment):
public static String replaceString(double number) {
NumberFormat formatter = new DecimalFormat("0.00");
return formatter.format(number);
}

Java: Format double to String with K, M, B

999 to 999
1000 to 1k
1500000 to 1.5m
and so on, I would like to not lose any precision at all
Also, need to convert them back to their original value
1.5m to 1500000
etc
The highest it would go is 11 digits max
Thanks
How about this:
import static java.lang.Double.parseDouble;
import static java.util.regex.Pattern.compile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
...
private static final Pattern REGEX = compile("(\\d+(?:\\.\\d+)?)([KMG]?)");
private static final String[] KMG = new String[] {"", "K", "M", "G"};
static String formatDbl(double d) {
int i = 0;
while (d >= 1000) { i++; d /= 1000; }
return d + KMG[i];
}
static double parseDbl(String s) {
final Matcher m = REGEX.matcher(s);
if (!m.matches()) throw new RuntimeException("Invalid number format " + s);
int i = 0;
long scale = 1;
while (!m.group(2).equals(KMG[i])) { i++; scale *= 1000; }
return parseDouble(m.group(1)) * scale;
}
If they weren't final you could extend java.lang.Integer etc. to override the toString() method. Is it worth creating a java.lang.Number subclass? Probably not. You could create your own classes: MyInteger, MyFloat etc using composition (they'll have an attribute to hold the numeric value) and override the toString() method to return the formats you want.
For the other way around, you could create factory methods in your MyXXX classes that creates objects containing the numeric value of the string (such as "1m").
The good thing is that kind of work lends itself well for unit testing.
You could probably obtain what you want by using directly a NumberFormat subclass but depending on how you're going to use it, the above design could be better.
static String[] prefixes = {"k","M","G"};
// Formats a double to a String with SI units
public static String format(double d) {
String result = String.valueOf(d);
// Get the prefix to use
int prefixIndex = (int) (Math.log10(d) / Math.log10(10)) / 3;
// We only have a limited number of prefixes
if (prefixIndex > prefixes.length)
prefixIndex = prefixes.length;
// Divide the input to the appropriate prefix and add the prefix character on the end
if (prefixIndex > 0)
result = String.valueOf(d / Math.pow(10,prefixIndex*3)) + prefixes[prefixIndex-1];
// Return result
return result;
}
// Parses a String formatted with SI units to a double
public static double parse(String s) {
// Retrieve the double part of the String (will throw an exception if not a double)
double result = Double.parseDouble(s.substring(0,s.length()-1));
// Retrieve the prefix index used
int prefixIndex = Arrays.asList(prefixes).indexOf(s.substring(s.length()-1)) + 1;
// Multiply the input to the appropriate prefix used
if (prefixIndex > 0)
result = result * Math.pow(10,prefixIndex*3);
return result;
}

Categories

Resources