Validate a String to Double with max digits - java
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);
}
Related
Numeric values from a String
I am creating a physics calculator and currently working on average velocity. For displacement I would like the user to input a string i.e. "5km north". Then using a method assign only the numeric values in the string to be doubles using Double.parseDouble or something of the like. Below is my method to pull out numeric values private double getNumericalValue(String userInput) { double numericalOutput = 0.0; for (int i = 0; i < userInput.length(); i++) { if (userInput.charAt(i) >= 65 && userInput.charAt(i) <= 122) { numericalOutput = Double.parseDouble(userInput.substring(0, i)); } } return numericalOutput; } and lastly the getAverageVelocity method private void getAverageVelocity() { // formula average velocity = displacement s / change in time t double avgVelocity = 0.0; System.out.println("Enter the displacement: [ex. 5 km north]"); String displacement = getStringInput(); System.out.println("Enter the change in time: [ex. 1 hour]"); String changeInTime = getStringInput(); // parse the string and change numerical input into double double numericalS = getNumericalValue(displacement); double numericalT = getNumericalValue(changeInTime); avgVelocity = numericalS / numericalT; System.out.println("The Average Velocity is: " + avgVelocity); } As you can see I figured I could simply compare chars to their ascii value. However, it is including the k or a space in my double output which is throwing this error. Exception in thread "main" java.lang.NumberFormatException: For input string: "5 k" at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.base/java.lang.Double.parseDouble(Double.java:556) at Main.getNumericalValue(Main.java:122) at Main.getAverageVelocity(Main.java:393) at Main.kineticsIn1DCalculator(Main.java:375) at Main.performAction(Main.java:141) at Main.runner(Main.java:29) at Main.main(Main.java:22) Any help and a thorough explanation would be great. Thanks.
What you are actually testing in the if block is whether the character at i is a letter A-Z, a-z and other symbols(i.e. [ ^ ], ...etc) to check if it's a number (i.e. 0-9) the corresponding decimal range is 48-57 check this link as for the exception it's because of substring(0, 0) will result in an empty string, and when trying to parse it, Double.parseDouble() will throw an exception. here is a solution you can use: private double getNumericalValue(String userInput) { double numericalOutput = 0.0; for (int i = 0; i < userInput.length(); i++) { if (userInput.charAt(i) >= 48 && userInput.charAt(i) <= 57) { numericalOutput = Double.parseDouble(userInput.substring(0, i + 1)); } } return numericalOutput; } Note: substring(i, j) i is inclusive, j exclusive Update : just noticed, in your case the exception happens because you are trying to parse the letter "k" since it passes the condition, resulting in Double.parseDouble() throwing an exception.
You have the error because even if the first number is found the for loop continues. You simply have to add break instruction, then the for loop ends at the first number found. This is the final code of the method getNumericalValue: private double getNumericalValue(String userInput) { double numericalOutput = 0.0; for (int i = 0; i < userInput.length(); i++) { if (userInput.charAt(i) >= 65 && userInput.charAt(i) <= 122) { numericalOutput = Double.parseDouble(userInput.substring(0, i)); break; } } return numericalOutput; }
You simply should input the line and parse its parts. Best to introduce a class to hold a value with unit, where "km north" counts as a unit. Since java 14 there exists the record class. record ValueWithUnit(double value, String unit) { public static ValueWithUnit from(String s) { String v = s.replaceFirst("^(.*?)([ A-z].*)$", "$1"); String u = s.replaceFirst("^(.*?)([ A-z].*)$", "$2"); if (u == v) { u = ""; } double x = Double.parseDouble(v); // Replaces getNumericalValue(v); return new Value(x, u); } #Override public String toString() { String.format("%f %s", value, unit); } } You could use it directly as: ValueWithUnit vu = new ValueWithUnit(30.0, "km"); System.out.println(vu); The code then becomes: private void getAverageVelocity() { // formula average velocity = displacement s / change in time t double avgVelocity = 0.0; System.out.println("Enter the displacement: [ex. 5 km north]"); ValueWithUnit displacement = ValueWithUnit.from(getStringInput()); System.out.println("Enter the change in time: [ex. 1 hour]"); ValueWithUnit changeInTime = ValueWithUnit.from(getStringInput()); // parse the string and change numerical input into double double numericalS = displacement.value; double numericalT = changeInTime.value; avgVelocity = numericalS / numericalT; System.out.printf("The Average Velocity is: %f %s%n", avgVelocity, displacement.unit + "/" + changeInTime.unit); }
Expanding a condensed string
I am trying take a string similar to this: 3A5o2n4t and expand it back to a string like this: AAAooooonntttt (the number in front of the letter is how many times the letter repeats) I was trying to use Integer.parseInt() to get the number in front of the letter, but it grabs all of the numbers. Is there a way to grab one number at a time? Also, does my code look okay after that issue is resolved? Or am I missing a bit still? public String runLengthDecoding(String str3) { String convert = ""; int number = 0; if (! str3.isEmpty()) { convert = str3.charAt(0) + ""; } for (int i = 0; i <= str3.length() - 1; i++) { if (Character.isDigit(str3.charAt(i))) { //true or false, the current character is a digit String temp = "" + str3.charAt(i); //if true, make that character a string number = Integer.parseInt(temp); /*now store that character as a number (but I only want the current number, not all the numbers in the string*/ System.out.println(number); /*Testing to see what number is, which is where I found it was storing all the numbers */ String temp2 = str3.charAt(i + 1) + ""; //Its supposed to start making a string that prints the character in front of it convert = temp2.repeat(number); //it will print the character however many times that number was stored as } } return convert; } Also I have not yet learned how to use arrays, that is why I am not using an array.
Edited to: - accommodate strings that has length more then 1. Example: 10AA - accommodate input that starts with a string. Example: A5o To solve this you have to get all the simultaneous digits, example if you have "55s", you have to get "55", That is why your code is incorrect since if you parseInt whenever you see a digit then it will immediately parse into 5, but the actual number is 55, thus you should accumulate the simultaneous digits first and only parseInt when you encounter the first non digit. Refer to the code and comments for details: public class Main { public static void main(String[] args) { System.out.println("Input: 3A5o2n4t => Output : " + runLengthDecoding("3A5o2n4t")); System.out.println("Input: 3AA5o2n4t => Output : " + runLengthDecoding("3AA5o2n4t")); System.out.println("Input: 10A5o2n4t => Output : " + runLengthDecoding("10A5o2n4t")); System.out.println("Input: 10AA5o2n4t => Output : " + runLengthDecoding("10AA5o2n4t")); System.out.println("Input: A5o => Output : " + runLengthDecoding("A5o")); System.out.println("Input: AB5o => Output : " + runLengthDecoding("AB5o")); } public static String runLengthDecoding(String str3) { String convert = ""; int number = 0; String numberString = ""; String toBeRepeatedString = ""; boolean flag = false; for (int i = 0; i <= str3.length() - 1; i++) { char currentChar = str3.charAt(i); if (Character.isDigit(currentChar)) { // true or false, the current character is a digit numberString = numberString + currentChar; // store the possible integer } else { if (i + 1 < str3.length()) { char nextChar = str3.charAt(i + 1); // check if the next char is a digit if (!Character.isDigit(nextChar)) { // if not a digit then append toBeRepeatedString if (i == 0 || i + 1 >= str3.length()) { flag = true; } else { toBeRepeatedString += nextChar; flag = false; } } else { flag = true; } } if (flag) { toBeRepeatedString += currentChar; // This will accomodate inputs "A3B"; if (!numberString.isEmpty()) { number = Integer.parseInt(numberString); // parse the number of repeats } else { number = 1; } numberString = ""; // reset number String temp2 = ""; // Repeat the currentChar for (int j = 0; j < number; j++) { temp2 += toBeRepeatedString; } convert = convert + temp2; // store it to the result toBeRepeatedString = ""; // reset toBeRepeatedString } } } return convert; } } Result: Input: 3A5o2n4t => Output : AAAooooonntttt Input: 3AA5o2n4t => Output : AAAAAAooooonntttt Input: 10A5o2n4t => Output : AAAAAAAAAAooooonntttt Input: 10AA5o2n4t => Output : AAAAAAAAAAAAAAAAAAAAooooonntttt Input: A5o => Output : Aooooo Input: AB5o => Output : ABooooo
Here is the best way of doing the above problem it will handle all your scenarios: public static void main(String[] args) { String input = "5a2s3T66e"; System.out.println("Input is: "+input+" and output is: "+expandingCondenseString(input)); } private static String expandingCondenseString(String input){ StringBuilder result = new StringBuilder(); String size = ""; String value = ""; for (int i=0;i<input.length();i++){ if (Character.isDigit(input.charAt(i))) { size = size + input.charAt(i); } else { value = value + input.charAt(i); if(i+1<input.length() && !Character.isDigit(input.charAt(i+1))){ continue; } if(size.isEmpty()){ size = "1"; } for (int j=0;j<Integer.parseInt(size);j++){ result.append(value); } size = ""; value = ""; } } return String.valueOf(result); }
Parse double without mantissa and exponent separator
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; }
Convert decimal to IEEE Binary
I am trying to convert a number from decimal value to its IEEE 752 form. For example: +43.9542 -> 01000010001011111101000100011010 -43.9542 -> 11000010001011111101000100011010 And I have written this method: public float GetFloat32(String numero) { //Convert int intBits = Integer.parseInt(numero, 2); float myFloat = Float.intBitsToFloat(intBits); //Exponent getExponent = 127 + (String.valueOf(Integer.toBinaryString(Math.abs((int) myFloat))).length() - 1); //Sign getSign = (myFloat < 0) ? 1 : 0; return myFloat; } There is a problem that I cannot solve. I will make another example to make it clear. double a = k.GetFloat32("01000010001011111101000100011010") a = 43.9542 But when the number is negative, such as double a = k.GetFloat32("1000010001011111101000100011010") I get this error: It means that my code works perfectly with positive numbers (including the zero) but with negative numbers it crashes. Where is the problem? Note I thought that I could solve my problem in this way Check if String numero has a charAt(0) equal at 1 If yes (numero.charAt(0) == 1) then remove the first char Call GetFloat32() with the new number (without the 1) Return the result adding the - in front of the num This could work but I would like to know where is the problem in the method above. I'd prefer avoiding this solution if possible.
The problem is that int/Integer has an upper limit of 0x7FFF_FFFF and so the Integer.parseInt method won't go beyond this limit. Use Long.parseLong, check the resulting value for exceeding 0x7FFF_FFFFL and handle according to the logic required for negative integer values. Although, I don't see anything bad in your very own idea of stripping the sign bit and dealing with the rest to get the absolute value. Edit There isn't a way to get the encoded float with a simple integer conversion from a bit string. Just consider that +1 and -1 in 32 binary digits according to two's complement representation differ in more than one bit, and 100....000 isn't -0. Signed magnitude isn't the same as two's complement. Moreover, Java's binary and hexadecimal (or any other base's) literals are meant to be positive quantities; if you need a negative value, use a sign. Later Method Integer.parseUnsignedInt doesn't have an advantage over using Long, since you'll then have to know how use two's complement arithmetic to remove the leading (sign) bit to produce the absolute value which can then be split into exponent and mantissa. (Add or subtract Integer.MIN_VALUE.) If there isn't IEEE 752 and IEEE 754 is the target format, the easiest form is float f1 = Float.intBitsToFloat(Integer.parseUnsignedInt(numerio,2));
public class IEEE754ToFloatingValues { public static double convertToInt(String mantissa_str) { int power_count = -1; double mantissa_int = 0.0; for (int i = 0; i < mantissa_str.length(); i++) { // System.out.print(Integer.parseInt(mantissa_str.charAt(i) + "")); mantissa_int += (Integer.parseInt(mantissa_str.charAt(i) + "") * Math.pow(2, power_count)); power_count -= 1; } IEEE754ToFloatingValues.logger.info((Object) "IEEE754ToFloatingValues : convertToInt :: end"); return mantissa_int + 1.0; } public static String convertToBinary(int i) { return Integer.toBinaryString(i + 0b10000).substring(1); } public static String decimalToHex(String decimal) { int i = Integer.parseInt(decimal); System.out.println("<<>>" + i); String my_hexdata = Integer.toHexString(i); System.out.println(my_hexdata); return String.valueOf(ReturnFloatingValue(my_hexdata)); } public static double ReturnFloatingValue(String my_hexdata) { String myString = ""; if (my_hexdata == null) { return -2.0; } if (my_hexdata.length() != 8) { myString = String.format("%1$-" + 8 + "s", my_hexdata).replace(' ', '0'); System.out.println("My hex data after appending 0's is : " + myString); } String binary = ""; for (int i = 0; i < myString.length(); i++) { int num = Integer.parseInt(myString.charAt(i) + "", 16); binary += convertToBinary(num); } System.out.println("Binary length is : " + binary.length()); System.out.println("Binary number is : " + binary); if (binary == null || binary.isEmpty()) { return -3.0; } String ieee_32 = binary.substring(2); ieee_32 = String.format("%1$-32s", binary).replace(' ', '0'); long sign_bit = Long.parseLong(new StringBuilder().append(ieee_32.charAt(0)).toString()); long exponent_bias = Long.parseLong(ieee_32.substring(1, 9), long exponent_unbias = exponent_bias - 127L; System.out.println("Exponent unbias is : " + exponent_unbias); String mantissa_str = ieee_32.substring(9); double mantissa_int = convertToInt(mantissa_str); double real_no = Math.pow(-1.0, (double) sign_bit) * mantissa_int * Math.pow(2.0, (double) exponent_unbias); System.out.println("Real no is : " + real_no); return real_no; } public static void main(String[] args) { //decimalToHex("0"); } }
import java.util.*; public class IEEE754 { public static void main(String[] args) { float floa; Scanner sc = new Scanner(System.in); System.out.println("ENTER A FLOATING POINT NUMBER"); floa=sc.nextFloat(); int no,sign; no=(int) floa; String a= Integer.toBinaryString(no); String sub=a.substring(1, a.length()); if(floa<0) { sign=1; } else { sign=0; } int exp=a.length()-1; System.out.println(exp); int be=127+exp; String b= Integer.toBinaryString(be); System.out.print("biased exponent->"); System.out.println(b); int loop=23-exp; float floatpart =floa-no; int q[]=new int[25]; for(int i=1,j=0;i<=loop;i++,j++) { q[j]=(int) (floatpart*2); floatpart=floatpart*2; if(q[j]==1){ floatpart=floatpart-1; } } System.out.print("mantissa->"); System.out.print(sub); for(int k=0;k<q.length;k++) System.out.print(q[k]); System.out.println(); System.out.println("IEEE754 FORMAT IS"); System.out.print(sign+" "+b+" "); System.out.print(sub); for(int k=0;k<q.length;k++) System.out.print(q[k]); } }
Displaying Currency in Indian Numbering Format
I have a question about formatting the Rupee currency (Indian Rupee - INR). Typically a value like 450500 is formatted and shown as 450,500. In India, the same value is displayed as 4,50,500 For example, numbers here are represented as: 1 10 100 1,000 10,000 1,00,000 10,00,000 1,00,00,000 10,00,00,000 Refer Indian Numbering System The separators are after two digits, except for the last set, which is in thousands. I've searched on the internet and people have asked to use the locale en_GB or pattern #,##,##,##,##0.00 I tried this on JSTL by using the following tag: <fmt:formatNumber value="${product.price}" type="currency" pattern="#,##,##,##,###.00"/> But this does not seem to solve the issue.
Unfortunately on standard Java SE DecimalFormat doesn't support variable-width groups. So it won't ever format the values exactly as you want to: If you supply a pattern with multiple grouping characters, the interval between the last one and the end of the integer is the one that is used. So "#,##,###,####" == "######,####" == "##,####,####". Most number formatting mechanisms in Java are based on that class and therefore inherit this flaw. ICU4J (the Java version of the International Components for Unicode) provides a NumberFormat class that does support this formatting: Format format = com.ibm.icu.text.NumberFormat.getCurrencyInstance(new Locale("en", "in")); System.out.println(format.format(new BigDecimal("100000000"))); This code will produce this output: Rs 10,00,00,000.00 Note: the com.ibm.icu.text.NumberFormat class does not extend the java.text.NumberFormat class (because it already extends an ICU-internal base class), it does however extend the java.text.Format class, which has the format(Object) method. Note that the Android version of java.text.DecimalFormat class is implemented using ICU under the hood and does support the feature in the same way that the ICU class itself does (even though the summary incorrectly mentions that it's not supported).
With Android, this worked for me: new DecimalFormat("##,##,##0").format(amount); 450500 gets formatted as 4,50,500 http://developer.android.com/reference/java/text/DecimalFormat.html - DecimalFormat supports two grouping sizes - the primary grouping size, and one used for all others.
here is simple thing u can do , float amount = 100000; NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("en", "IN")); String moneyString = formatter.format(amount); System.out.println(moneyString); The output will be Rs.100,000.00.
I also got myself in same problem. I was working with DecimalFormat. I have no knowledge of JSTL but you can figure out something by my solution. As, grouping size remains constant in DecimalFormat. I separated both parts, formatted them with different patterns and concat both. Here is the code. public static String format(double value) { if(value < 1000) { return format("###", value); } else { double hundreds = value % 1000; int other = (int) (value / 1000); return format(",##", other) + ',' + format("000", hundreds); } } private static String format(String pattern, Object value) { return new DecimalFormat(pattern).format(value); } It will provide format like Indian Numbering System. If you want decimal points, just add ".##" in both conditions. "###" to "###.##" and "000" to "000.##".
public String getIndianCurrencyFormat(String amount) { StringBuilder stringBuilder = new StringBuilder(); char amountArray[] = amount.toCharArray(); int a = 0, b = 0; for (int i = amountArray.length - 1; i >= 0; i--) { if (a < 3) { stringBuilder.append(amountArray[i]); a++; } else if (b < 2) { if (b == 0) { stringBuilder.append(","); stringBuilder.append(amountArray[i]); b++; } else { stringBuilder.append(amountArray[i]); b = 0; } } } return stringBuilder.reverse().toString(); } This is what i did, for getting Indian currency format. if input is 1234567890 means output is 1,23,45,67,890.
Try this: NumberFormat.getCurrencyInstance(new Locale("en","IN")).format(number) "en" is for English. "IN" is for the country (India).
Just Copy past this function. :) public static String rupeeFormat(String value){ value=value.replace(",",""); char lastDigit=value.charAt(value.length()-1); String result = ""; int len = value.length()-1; int nDigits = 0; for (int i = len - 1; i >= 0; i--) { result = value.charAt(i) + result; nDigits++; if (((nDigits % 2) == 0) && (i > 0)) { result = "," + result; } } return (result+lastDigit); }
The simple solution is - Double amount = 5356673553123.0; //amount is an example ,can be used with any double value **DecimalFormat IndianCurrencyFormat = new DecimalFormat("##,##,###.00");** then use it as - String formattedAmount = IndianCurrencyFormat.format(amount);
Please find below snippet to print currency according to locale by giving inputs import java.util.*; import java.text.*; public class CurrencyPayment { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double payment = scanner.nextDouble(); scanner.close(); System.out.println("US: " + NumberFormat.getCurrencyInstance(Locale.US).format(payment)); System.out.println("India: " + NumberFormat.getCurrencyInstance(new Locale("en","IN")).format(payment)); System.out.println("China: " + NumberFormat.getCurrencyInstance(Locale.CHINA).format(payment)); System.out.println("France: " + NumberFormat.getCurrencyInstance(Locale.FRANCE).format(payment)); } }
If there is no default Locale available and the user doesn't make any change to the locale, we can go with setting the currency symbol using unicode and decimal formatting. As in the below code: For e.g. Setting the Indian currency symbol and formatting the value. This will work without user making changes in the settings. Locale locale = new Locale("en","IN"); DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getCurrencyInstance(locale); DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale); dfs.setCurrencySymbol("\u20B9"); decimalFormat.setDecimalFormatSymbols(dfs); System.out.println(decimalFormat.format(payment)); Output: ₹12,324.13
On Android android.icu.text.NumberFormat is available after api level 24 only. So to support lower version I wrote my own method in java. public static String formatIndianCommaSeparated(long rupee){ // remove sign if present String raw = String.valueOf(Math.abs(rupee)); int numDigits = raw.length(); StringBuilder sb = new StringBuilder(raw); // Reverse the string to start from right most digits sb = sb.reverse(); // Counter to keep track of number of commas placed int commas = 0; for (int i=0; i<numDigits; i++){ // Insert a comma if i is in the range [3, 5, 7, 9, ...) if (i % 2 == 1 && i != 1 ){ sb.insert(i+commas, ","); commas++; } } // Reverse the string back to get original number String sign = (rupee < 0) ? "-" : ""; return sign + sb.reverse().toString(); }
Kotlin version, It works on Android API 26 fun currencyLocale(value: Double): String { val formatter = NumberFormat.getCurrencyInstance(Locale("en", "in")) return formatter.format(value) } fun parseCommaSeparatedCurrency(value: String): Number { return NumberFormat.getCurrencyInstance(Locale("en", "in")).parse(value) }
Few options that I explored are as below import java.text.NumberFormat; import java.util.Locale; class NumberFormatDemo { public static void main(String[] args) { Double d = 45124853123456.78941; NumberFormat nf = NumberFormat.getInstance(Locale.ITALY); System.out.println("ITALY representation of " + d + " : " + nf.format(d)); nf = NumberFormat.getInstance(Locale.GERMANY); System.out.println("GERMANY representation of " + d + " : " + nf.format(d)); nf = NumberFormat.getInstance(Locale.CHINESE); System.out.println("CHINESE representation of " + d + " : " + nf.format(d)); nf = NumberFormat.getInstance(Locale.US); System.out.println("US representation of " + d + " : " + nf.format(d)); nf = NumberFormat.getInstance(Locale.ENGLISH); System.out.println("ENGLISH representation of " + d + " : " + nf.format(d)); nf = NumberFormat.getInstance(Locale.UK); System.out.println("UK representation of " + d + " : " + nf.format(d)); //=================================================== //ICU4j example com.ibm.icu.text.NumberFormat format = com.ibm.icu.text.NumberFormat.getCurrencyInstance(new Locale("en", "in")); System.out.println("INDIA representation of " + d + " : " + nf.format(d)); } } The last one reacquires following dependency <dependency> <groupId>com.ibm.icu</groupId> <artifactId>icu4j</artifactId> <version>65.1</version> </dependency>
//Input: long num = 450500; // Unlike other countries, there is no direct Locale field for India.Therefore, we need to construct a locale for India. Locale loc = new Locale("en", "in"); // This will display currency with "Rs." symbol. // or use below to display currency with "INR" symbol. Locale loc = new Locale("", "in"); NumberFormat indiacurrency = NumberFormat.getCurrencyInstance(loc); String result = indiacurrency.format(num); System.out.print(result);
public static String paiseToString(long paise) { DecimalFormat fmt = new DecimalFormat("#0.00"); boolean minus = paise < 0; StringBuilder sb = new StringBuilder(fmt.format(Math.abs(paise)/100.0)); for (int index = sb.length()-6; index > 0; index-=2) { sb.insert(index,','); } if (minus) sb.insert(0,'-'); return sb.toString(); } public static String rupeesToString(long rupees) { boolean minus = rupees < 0; StringBuilder sb = new StringBuilder(Long.toString(Math.abs(rupees))); for (int index = sb.length()-3; index > 0; index-=2) { sb.insert(index,','); } if (minus) sb.insert(0,'-'); return sb.toString(); } // Test the functions public static void main(String[] args) { // Test for positive values long val = 1; while (val < Long.MAX_VALUE/10) { System.out.printf("%28s %28s\n",paiseToString(val),rupeesToString(val)); val *= 10; } // Test for negative values val = -1; while (val > Long.MIN_VALUE/10) { System.out.printf("%28s %28s\n",paiseToString(val),rupeesToString(val)); val *= 10; } }
The default methods in existing libraries can only show thousands seperator. so we need to write custom function for this. You can use multiple substring operation to get the desired result. In java, function indianCurrencyNumberFormat(rupee) { string explore_remaining_units = ""; if (rupee.length() > 3) { last_three_digits = rupee.substring((rupee.length()-3), rupee.length()); remaining_units = rupee.substring(0, (rupee.length()-3)); remaining_units = ((remaining_units.length()) % 2 == 1) ? "0"+remaining_units : remaining_units; split_rupee = remaining_units.split("(?<=^(.{2})+)") for (i = 0; i < sizeof(split_rupee); i++) { explore_remaining_units += ((i == 0) ? ( (int) split_rupee[i]+"," ) : ( split_rupee[i]+"," )); } formatted_rupee = explore_remaining_units+last_three_digits; } else { formatted_rupee = rupee; } return formatted_rupee; } And in php: function indianCurrencyNumberFormat($rupee) { $explore_remaining_units = ""; if (strlen($rupee) > 3) { $last_three_digits = substr($rupee, strlen($rupee) - 3, strlen($rupee)); $remaining_units = substr($rupee, 0, strlen($rupee) - 3); $remaining_units = (strlen($remaining_units) % 2 == 1) ? "0".$remaining_units : $remaining_units; $split_rupee = str_split($remaining_units, 2); for ($i = 0; $i < sizeof($split_rupee); $i++) { $explore_remaining_units .= (($i == 0) ? ( (int) $split_rupee[$i] . "," ) : ( $split_rupee[$i] . "," )); } $formatted_rupee = $explore_remaining_units.$last_three_digits; } else { $formatted_rupee = $rupee; } return $formatted_rupee; } You can see more details here.
import java.util.*; public class string1 { public static void main(String args[]) { int i,j; boolean op=false; StringBuffer sbuffer = new StringBuffer(); Scanner input = new Scanner(System.in); System.out.println("Enter a string"); sbuffer.append(input.nextLine()); int length=sbuffer.length(); if(sbuffer.length()<3) { System.out.println("string="+sbuffer); } else { for ( i = sbuffer.length(); i >0; i--) { if (i==length-3) { sbuffer.insert(i, ","); op=true; } while(i>1 && op==true) { i=i-2; if(i>=1) { sbuffer.insert(i, ","); } } } } System.out.println("string="+sbuffer); } }
It is better answer and works dynamically instead of specifying single Locale in code manually. public String convertToDefaultCurrencyFormat(String amountToConvert){ NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.getDefault()); String moneyString = formatter.format(Double.valueOf(amountToConvert)); return moneyString; } for Indian rupees format change Language in your Android device: Setting > Language & Input Settings > choose English(India) Output: ₹10,00,000 (Starting with Indian Rupee symbol)
Working fine for me in Android: public static String priceFormatWithDec(String price) { DecimalFormat decimalFormat = new DecimalFormat("#,##,###.00"); String format = decimalFormat.format(Double.parseDouble(price)); return String.format("%s", format); }
using Locale class and getCurrencyInstance the Indian currency format can be obtained. while defining the new Locale for India use "en" for English and "hi" for Hindi. for locale refer https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html for getCurrencyInstance refer https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getCurrencyInstance-- here is a small implementation of the same. import java.util.*; import java.text.*; import java.text.NumberFormat; import java.util.Locale; public class Solution { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double payment = scanner.nextDouble(); scanner.close(); Locale indialocale=new Locale("en","IN"); NumberFormat india = NumberFormat.getCurrencyInstance(indialocale); System.out.println("India: " + india.format(payment)); } }
This is working for me .. public String indianCurrencyFormat(String s) { String orignalNo = s; String formatted = ""; if(orignalNo.startsWith("-")) { s = s.replace("-",""); } if(orignalNo.contains(".")) { if(s.length() > 6){ StringBuilder sb=new StringBuilder(s); s = sb.reverse().toString(); formatted = s.substring(0,6); s = s.substring(6); while(s.length() > 1) { formatted += "," + s.substring(0,2); s = s.substring(2); } sb = new StringBuilder(formatted+(StringUtils.isNotBlank(s) ? ","+s :"")); formatted = sb.reverse().toString(); } else { formatted = s; } } else { if(s.length() > 3){ StringBuilder sb=new StringBuilder(s); s = sb.reverse().toString(); formatted = s.substring(0,3); s = s.substring(3); while(s.length() > 1) { formatted += "," + s.substring(0,2); s = s.substring(2); } sb = new StringBuilder(formatted+(StringUtils.isNotBlank(s) ? ","+s :"")); formatted = sb.reverse().toString(); } else { formatted = s; } } if (orignalNo.startsWith("-")){ formatted = "-"+formatted; } return formatted; }
It worked for me: fun getFormattedPrice(price: Double?): String { if (price == null) return "0" val formatter = DecimalFormat("##,##,###.00").format(price) var formattedPrice = formatter.format(price) if (formattedPrice.endsWith(".00")) formattedPrice = formattedPrice.dropLast(3) if (formattedPrice.isEmpty()) formattedPrice = "0" return formattedPrice }
Try this: double number = 100000.00 NumberFormat numberFormat = new NumberFormat(); Locale locale = new Locale("hi","IN"); numberFormat = Numberformat.getCurrencyInstance(locale); double yourFormattedNumber = numberFormat(number); OutPut = ₹1,00,000.00 //Remove "₹" using String.replace() String myFormattedNumber = numberFormat.format(number).replace("₹",""); OutPut = 1,00,000.00
fun currencyFormatter(inputNumbers: String?): String { var formattedNumber = "" var decimalPoint="" var inputNumber="" if (inputNumbers != null) { try { val sp=inputNumbers.split(".") inputNumber=sp[0] decimalPoint=sp[1] } catch (e: Exception) { inputNumber=inputNumbers } formattedNumber = when { inputNumber.length <= 3 -> { inputNumber } inputNumber.length <= 5 -> { String.format("%s,%s", inputNumber.substring(0, inputNumber.length - 3), inputNumber.substring(inputNumber.length - 3)) } inputNumber.length <= 7 -> { String.format("%s,%s,%s", inputNumber.substring(0, inputNumber.length - 5), inputNumber.substring(inputNumber.length - 5, inputNumber.length - 3), inputNumber.substring(inputNumber.length - 3) ) } inputNumber.length <= 9 -> { String.format("%s,%s,%s,%s", inputNumber.substring(0, inputNumber.length - 7), inputNumber.substring(inputNumber.length - 7, inputNumber.length - 5), inputNumber.substring(inputNumber.length - 5, inputNumber.length - 3), inputNumber.substring(inputNumber.length - 3) ) } else -> inputNumber } } return "$formattedNumber.$decimalPoint" } main(){ val rs=1200.55f print(currencyFormatter(rs.toString())) }
Converting any Number into Indian Rupee Format in Golang. Function IndianRupeeFormat takes paramter as string and returns as string func IndianRupeeFormat(DisplayAmount string) string { AmountDisplayed := DisplayAmount[:len(DisplayAmount)-3] // just removing decimal point numbers. IndianRupee := "" if len(AmountDisplayed) > 3 { // amount should to greater than 999 if "," should appear , so length should be greater than 3 startIndex := math.Mod(float64(len(AmountDisplayed)), 2) // startIndex is taken as slicing part to add comma. noOfCommas := (len(AmountDisplayed) / 2) - 1 // No of Commas appear in the number. startSlice := 0 // start of the slice for i := 0; i < noOfCommas; i++ { IndianRupee = IndianRupee + DisplayAmount[startSlice:int64(startIndex)+1] + "," startIndex = startIndex + 2 // adding +2 because after first comma we are skipping 2 digits to add another comma. startSlice = int(startIndex) - 1 } k := len(DisplayAmount) - 6 IndianRupee = IndianRupee + DisplayAmount[k:] // adding the rest of digits. } else { IndianRupee = DisplayAmount } return IndianRupee } Amount1 := IndianRupeeFormat(fmt.Sprintf("%.2f",100)) Amount2 := IndianRupeeFormat(fmt.Sprintf("%.2f",1000.345)) Amount3 := IndianRupeeFormat(fmt.Sprintf("%.2f",10000.02)) Amount4 := IndianRupeeFormat(fmt.Sprintf("%.2f",100000.100)) Amount5 := IndianRupeeFormat(fmt.Sprintf("%.2f",1000000.)) Amount6 := IndianRupeeFormat(fmt.Sprintf("%.2f",1000.090)) fmt.Println(Amount1) fmt.Println(Amount2) fmt.Println(Amount3) fmt.Println(Amount4) fmt.Println(Amount5) fmt.Println(Amount6) // Output: 100 // Output: 1,000.34 // Output: 10,000.02 // Output: 1,00,000.10 // Output: 10,00,000.00 // Output: 1,000.90
I know this is an old question but I'll add my answer just in case. It is possible to use the same decimal formatter in a roundabout way to achieve the result but it isn't the most efficient solution, just a simpler one. import java.math.RoundingMode; import java.text.DecimalFormat; public class IndianMoneyFormat { static String indianCurrencyFormat(double money) { String result = null; double aboveThousands = money / 1000; double thousands = money % 1000; if (aboveThousands > 1) { DecimalFormat formatter = new DecimalFormat("##,##"); formatter.setRoundingMode(RoundingMode.DOWN); //will round towards zero whether negative or positive. Same as truncating. String one = formatter.format(aboveThousands); formatter.applyPattern("###.00"); formatter.setRoundingMode(RoundingMode.HALF_EVEN); //default rounding mode of DecimalFormat String two = formatter.format(thousands); result = one + "," + two; return result; } else { DecimalFormat formatter = new DecimalFormat("###.00"); result = formatter.format(money); return result; } } public static void main(String[] args) { double money1 = 123000999.5; double money2 = 999.39; System.out.println(indianCurrencyFormat(money1)); System.out.println(indianCurrencyFormat(money2)); } } Above code will provide the following result: 12,30,00,999.50 999.39
ALTER FUNCTION [dbo].[udf_CurrencyFormat](#UC varchar(50)) RETURNS varchar(50) AS BEGIN declare #FC varchar(50),#Scale varchar(3),#i bigint=1,#a int=3,#b int=2,#WhileLength bigint,#UCScale varchar(50), #Con varchar(20) set #Scale=charindex('.',#UC) --if number has '.' then value else '0' if(#Scale!='0') begin set #UCScale=#UC set #Con=substring(#UCScale,charindex('.',#UCScale),3) set #UC=substring(#UC,0,charindex('.',#UC)) -- substring end if(cast(len(#UC) as bigint)%2!=0) --if odd begin set #WhileLength=(cast(len(#UC) as bigint)-3)/2 while(#i<=#WhileLength) -- length-3/2=3 if length is 9 (cast(len(#UC) as bigint)-3)/2 begin set #a=3*#i set #UC = stuff(#UC,#a,0,',') set #i=#i+1 end --while set #FC=#UC end --if odd Scale '0' else if(cast(len(#UC) as bigint)%2=0) --if even begin set #WhileLength=(((cast(len(#UC) as bigint)-1)-3)/2)+1 while(#i<=#WhileLength) begin if(#i=1) begin set #UC=stuff(#UC,#b,0,',') end else begin set #b=#b+3 set #UC=stuff(#UC,#b,0,',') end set #i=#i+1 end set #FC=#UC end if(#Scale!='0') begin set #FC=#FC+#Con end --if(#Scale!='0') --set #FC=#UC return #FC END