Suppose you code a simple divide program in Java and run it. Now suppose it gives you this answer 451.12531 . But you want to select only a single or two digit from this answer may be before the point or after it. In this case we assume that we need to select. Second number which is 5. And you want to print this only. How do you do that?
This can be done by converting your Double to a String using:
String s = String.valueOf(double);
You can then use the Character.getNumericValue() method to get the desired number/position:
int x = Character.getNumericValue(s.charAt(1));
Full example:
Double d = 451.12531;
String s = String.valueOf(d);
int x = Character.getNumericValue(s.charAt(1));
where x is your desired number, in the above example it will be 5
Try this :
private void selectSingleDigit(double number) {
String noInStringFormat = String.valueOf(number);
int digit = getDigitAtSpecificDigit(2,noInStringFormat);
System.out.println(digit);
}
private int getDigitAtSpecificDigit(int index,String str){
if (str != null && !str.isEmpty()) {
return Integer.parseInt(String.valueOf(str.charAt(index)));
} else return -1;
}
Try using this, here d1 will have digits before decimal point and d2 will have digits after decimal point.
String d1 = text.substring( 0,text.indexOf('.'))
String d2 = text.substring( text.indexOf('.'), text.length());
Related
For example when I parse a string "12345678901234567890" to double using Double.parseDouble() it returns the value "12345678901234567000" since it can hold up to 17 digits.
I want to validate this scenario and the user should be allowed to pass only 17 digits. How do I do this?
Example :
1.2345678901234567890 is invalid because it has more than 17 digits total
1.2345E+10 is valid
Tried something like this which can count the digits using split function
String input="12345678901234567E100";
String inputWithoutSign;
int lengthFullNumber;
int lengthFraction;
double v = Double.parseDouble(input);
if(input.startsWith("+") || input.startsWith("-")){
inputWithoutSign = input.split("[-+]",2)[1];
}
else inputWithoutSign = input;
String num = inputWithoutSign.split("[eE]", 2)[0];
if(num.indexOf('.') == -1){
lengthFullNumber = num.length();
lengthFraction = 0;
}else{
String[] splitNum = num.split("\\.", 2);
lengthFullNumber = splitNum[0].length();
lengthFraction = splitNum[1].length();
}
System.out.println("length:"+(lengthFullNumber+lengthFraction));
Presuming I understand your goal of limiting the number of digits, this may help solve the problem.
Test cases
String[] vals = {
"12345678901234567890", "123456789091919191919",
"182828282.18282828", "182828282.182828282", "191929e10",
"192929.22929e10"
};
Try and parse them
for (String v : vals) {
// remove possible decimal point and signs
String test = v.replaceAll("[.+-]", "");
// remove any exponents at end of string
test = test.replace("\\D+.*", "");
if (test.length() > 17) {
System.out.println(v + " has too many digits");
continue;
}
double d = Double.parseDouble(v);
System.out.println(v + " parses to " + d);
}
I have to read double from data files with the following format
1.234+5 // = 1.234e+5
1.234-5 // = 1.234e-5
I can't change the format and I have to parse millions/billions double from data files(= method should be efficient) .
Can I provide a decimal format or is there a convenient method (available in java jdk) able to parse these doubles ?
Double.parseDouble("1.234+5"); // throws NumberFormatException
Scanner scanner = new Scanner("1.234+5");
Scanner.nextDouble(); // throws InputMismatchException
EDIT 1
Precision for what i call data files :
Data files are ENDF formatted file which is a really strict format (300 pages manual) and here is an extract of one of these files
9.223500+4 2.330248+2 0 0 0 63515 8457
2.22102+16 1.57788+13 0 0 6 03515 8457
4.170051+4 1.312526+3 1.641191+5 1.625818+3 4.413323+6 1.648523+53515 8457
I can parse integers with a simple
Integer.parseInt()
But i can't with double.
You can use a regex to insert an e which is then parseable in the normal way:
private static final Pattern INSERT_EXPONENT = Pattern.compile("(.*)([+-].*)");
System.out.println(INSERT_EXPONENT.matcher("1.234+5").replaceFirst("$1e$2"));
System.out.println(INSERT_EXPONENT.matcher("1.234-5").replaceFirst("$1e$2"));
This is just quick&dirty and doesn't guard against invalid input.
Here is my attempt. I don't know if this is what you are looking for, but this will convert the number into a double format. Hope this will help.
String temp = "1.234+5";
StringBuilder str = new StringBuilder(temp);
for(int index = temp.length() - 1; index > 0; index--)
{
//this will look for a + or - symbol in your string
if(temp.charAt(index) == '+' || temp.charAt(index) == '-') {
str.insert(index, 'e'); //this will insert e before the symbol
break;
}
}
temp = str.toString();
System.out.println(temp);
double a= Double.parseDouble(temp); //convert the string back to a double
System.out.println(a); //this is just to test the output
double b = 1.234e+5;
System.out.println(b);
You will probably need a regex.
private void test() {
String [] test = {"1.234+5", "-1.234-2"};
for (String s : test) {
System.out.println(s + " -> " + parse(s));
}
}
private static final Pattern FindMissingE = Pattern.compile("([+-]{0,1}[0-9.]+)([+-]{0,1}[0-9]+)");
private double parse(String s) {
Matcher m = FindMissingE.matcher(s);
if(m.find()) {
return Double.parseDouble(m.replaceFirst("$1e$2"));
}
return 0.0;
}
I am trying to write a program to determine the sum of the digits in a string using recursion, I thought that the following code would print "The sum is 6" to the console but instead it outputs "The code is 150".
Could someone please tell me what my mistake is?
public class SumOfString {
public static String Test = new String();
public static Integer count = new Integer(0);
public static Integer sum = new Integer(0);
public static long sumThis(String s){
if (count< s.length()){
if (Character.isDigit(s.charAt(count))){
int digit = s.charAt(count);
count++;
sum += digit;
return sumThis(s);}
else{
count++;
return sumThis(s);}}
else{
return sum;}}
public static void main(String[] args) {
Test= "1a2b3c";
System.out.println("The sum is " + sumThis(Test));
}
Without solving the problem for you:
One bug in your code is :
int digit = s.charAt(count);
Test this snippet of code on the String "1" with a count of 0. It does not return the integer 1. To get that, you need to wrap this call :
Character.getNumericValue(s.charAt(count));
You should really get in the habit of running your code in the debugger.
Have a look at a ascii table as you will see that the value of "1" is 49, "2" is 50 and "3" is 51 summing to 150
try
int digit = s.charAt(count) - 48;
The cause of this is the line at
int digit = s.charAt(count);,
charAt will return a character primitive therefore it will be the decimal value of that character.
Character = Decimal Value
`1` = 49
`2` = 50
`3` = 51
-------
150
You need to convert the character to int: Java: parse int value from a char
I'm creating a feet and inches calculator. I want the user to be able to enter the information in various ways such as 1'-4-5/8" or 1 4 5/8.
When performing math, the above numbers will have to be converted to decimal (1'-4-5/8" is 16.625 in decimal inches). The final result will be in either decimal inches or then converted back to feet and inches.
How would I go about parsing the architectural measurement and converting it into decimal inches?
Any help would be greatly appreciated!
Thank you!
edit:
After way too much time and trying many different things, I think I got something that will work. I'm ultimately going to limit the way the user can enter the length so I think the following is going to work. It may not be optimized but it's the best I can get right now.
public class delim_test_cases {
public static void main(String[] args) {
double inches = 0;
double feet = 0;
double fract = 0;
String str = "2'-3-7/8";
String[] TempStr;
String delimiter = ("[-]+");
TempStr = str.split(delimiter);
for(int i=0; i< TempStr.length ; i++ ) {
for(int z=0; z< TempStr[i].length() ; z++ ) {
if (TempStr[i].charAt(z) == '\'') {
String[] FeetStr;
String feetdelim = ("[\']+");
FeetStr = TempStr[i].split(feetdelim);
feet = Integer.parseInt(FeetStr[0]);
}
else if (TempStr[i].charAt(z) == '/') {
String[] FracStr;
String fracdelim = ("[/]+");
FracStr = TempStr[i].split(fracdelim);
double numer = Integer.parseInt(FracStr[0]);
double denom = Integer.parseInt(FracStr[1]);
fract = numer/denom;
}
else if (TempStr[i].indexOf("\'")==-1 && TempStr[i].indexOf("/")==-1) {
String inchStr;
inchStr = TempStr[i];
inches = Integer.parseInt(inchStr);
}
}
}
double answer = ((feet*12)+inches+fract);
System.out.println(feet);
System.out.println(inches);
System.out.println(fract);
System.out.println(answer);
}
}
Why not just split on either the '-' or a space, then you have an array of possibly 3 strings.
So, you look at the last character, if it is a single quote, then multiply that by 12.
If a double quote, then split on '/' and just calculate the fraction, and for a number that is neither of these it is an inch, just add it to the total.
This way you don't assume the order or what if you just have fractional inches.
Just loop through the array and then go through the algorithm above, so if someone did
3'-4'-4/2" then you can calculate it easily.
UPDATE:
I am adding code based on the comment from the OP.
You may want to refer to this to get more ideas about split.
http://www.java-examples.com/java-string-split-example
But, basically, just do something like this (not tested, just written out):
public double convertArchToDecimal(String instr, String delimiter) {
String[] s = instr.split(delimiter);
int ret = 0;
for(int t = 0; t < s.length; t++) {
char c = s[t].charAt(s[t] - length);
switch(c) {
case '\'': //escape single quote
String b = s[t].substring(0, s[t].length - 1).split("/");
try {
ret += Integer.parse(s[t].trim()) * 12;
} catch(Exception e) { // Should just need to catch if the parse throws an error
}
break;
case '"': // may need to escape the double quote
String b = s[t].substring(0, s[t].length - 1).split("/");
int f = 0;
int g = 0;
try {
f = Integer.parse(b[0]);
g = Integer.parse(b[1]);
ret += f/g;
} catch(Exception e) {
}
break;
default:
try {
ret += Integer.parse(s[t].trim());
} catch(Exception e) { // Should just need to catch if the parse throws an error
}
break;
}
}
return ret;
}
I am catching more exceptions than is needed, and you may want to use the trim() method more than I did, to strip whitespace before parsing, to protect against 3 / 5 " for example.
By passing in a space or dash it should suffice for your needs.
You may also want to round to some significant figures otherwise rounding may cause problems for you later.
I have a number as a string like this: "9.756088256835938E-4" but I only can use a specified number of characters (in this special case 9 char). So I want to have something like this: "9.7561E-4". I already tried to convert the String to a Double and then used the format method to get a less characters but I don't got a correct solution.
The problem is that I need ten exponential output since some numbers are longer than the number of characters I have. If it is possible, the number should be displayed with no ten exponent, if not just use the ten exponent.
Also correct rounding would be good.
And it should work for negative numbers. (minus needs one character!!!)
Is there a format function where I can define the maximum length of the output string? Any ideas?
I'm having trouble findind a single format pattern that will cover all of the cases that you described. But here's a combination of logic that I think works:
public static void main(String[] args) throws Exception {
// 97.560883
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+1")));
// 9.756E+11
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+11")));
// 0.0009756
System.out.println(formatNum(Double.parseDouble("9.756088256835938E-4")));
// -9.8E+111
System.out.println(formatNum(Double.parseDouble("-9.756088256835938E+111")));
}
private static final int MAX_LENGTH = 9;
private static String formatNum(double number) {
String out = null;
for ( int i = 0; i < MAX_LENGTH; i++ ) {
String format = "%." + i + "G";
out = String.format(format, number);
if ( out.length() == MAX_LENGTH ) {
return out;
}
}
return out; //the best we can do
}
The "G" in the pattern instructs the formatter to forego the use of the exponent when it will allow for the same or better precision. We grow up to the maximum length and stop when our output string is 10 characters. I think you could take the same approach with a DecimalFormat, but I'm more familiar with Formatter.
Seeing the Mark's example meet your requirements, I updated my answer to show the DecimalFormat implementation. I used Mark's test cases. It is definitely an uglier option because there is no easy way to turn on/off exponents. The only advantage over the String.format option is that it handles very small numbers well.
public static void main(String[] args) throws Exception {
// 97.560883
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+1")));
// 9.756E+11
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+11")));
// 0.0009756
System.out.println(formatNum(Double.parseDouble("9.756088256835938E-4")));
// -9.8E+111
System.out.println(formatNum(Double.parseDouble("-9.756088256835938E+111")));
}
private static final int MAX_LENGTH = 9;
private static String formatNum(double number) {
int digitsAvailable = MAX_LENGTH - 2;
if (Math.abs(number) < Math.pow(10, digitsAvailable)
&& Math.abs(number) > Math.pow(10, -digitsAvailable)) {
String format = "0.";
double temp = number;
for (int i = 0; i < digitsAvailable; i++) {
if ((temp /= 10) < 1) {
format += "#";
}
}
return new DecimalFormat(format).format(number);
}
String format = "0.";
for (int i = 0; i < digitsAvailable; i++) {
format += "#";
}
String r = new DecimalFormat(format + "E0").format(number);
int lastLength = r.length() + 1;
while (r.length() > MAX_LENGTH && lastLength > r.length()) {
lastLength = r.length();
r = r.replaceAll("\\.?[0-9]E", "E");
}
return r;
}
This reminded me of a similar question where the OP only had 5 or so spaces for a number and wanted to show a decimal only when there was enough space. But instead of exponents, wanted to use a suffix of (k,m, etc)