This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 1 year ago.
I want to remove zeroes from my string as decimal places, but I am not able to do that. Also, I want the decimal places gone only if zeros are there else the decimal places will be there.
Example:
1234.00 should become 1234
1234.25 should remain 1234.25
Here is the code I am using to do that but its not working.
String price_normal2 ="1234.00";
if(price_normal2.contains(".00")){
price_normal2.replace(".00","");
Log.i("PRICEEEEE",""+price_normal2);
}
Please help me in this.
String class are immutable, So replace method will not replace the value in same object instead it will return the new string which can you store it into another object or the same object by assigning it.
String price_normal2 ="1234.00";
if(price_normal2.contains(".00")){
price_normal2 = price_normal2.replace(".00","");
Log.i("PRICEEEEE",""+price_normal2);
}
Parse the price to double to ensure the validity and then convert it to integer
public static void main(String[] args) {
String price_normal2 = "1234.00";
double priceWithFraction = Double.parseDouble(price_normal2);
int price = (int) priceWithFraction;
System.out.println("Price " + price);
}
check this one it will remove the decimal part if it all are zero or remove the any zero on the left side
NumberFormat numberFormat = DecimalFormat.getNumberInstance();
numberFormat.setMinimumFractionDigits(0);
System.out.println(numberFormat.parse("1234.001"));
is it fine with you that 1234.40 be 1234.4 or you want it to be 1234.40?
you can use DecimalFormat class
DecimalFormat decimalFormat = new DecimalFormat("00.##");
String formatted = decimalFormat.format(Double.parseDouble("1234.30"));
String[] splitted = formatted.split("\\.");
if (splitted.length > 1) {
String dec = (splitted[1].length() == 1) ? splitted[1] + "0" : splitted[1];
formatted = splitted[0] + "." + dec;
}
logs
D/mridx: main: 1234.30
Related
So at the input, a string contains different types of data. Basically, this is a string, int, and float. I check types through Float.parseFloat() and Integer.parseInt(). the Integer.parseInt() works correctly, yet Float.parseFloat() includes all the digits that are checked. How to avoid this?
The problem is that when checking for the float type, it also considers ints (output):
Hello my 50 name 4.5 is James, I 20 years old and I have 5.7 coins
Float 4
Int 2
String 12
public class TypeCountString {
public static void countTypeInString(String string){
String[] value = string.split(" ");
float ifFloat;
int ifInt;
String ifString;
int counter = 0;
// count Floats
for (String i: value){
try{
ifFloat = Float.parseFloat(i);
counter++;
continue;
} catch (NumberFormatException e){
}
}
System.out.println("Float " + counter);
//count ints
counter = 0;
for (String i: value){
try{
ifInt = Integer.parseInt(i);
counter++;
continue;
} catch (NumberFormatException e){
}
}
System.out.println("Int " + counter);
//counts strings
String stringOfStrings = string.replaceAll("[0-9.]","");
stringOfStrings = stringOfStrings.replaceAll(" "," ");
String[] value2 = stringOfStrings.split(" ");
System.out.println("String " + value2.length);
}
public static void main(String[] args) {
String string = "Hello my 50 name 4.5 is James, I 20 years old and i have 5.7 coins";
System.out.println(string);
countTypeInString(string);
}
}
As Integer is a sub-type of Float, Float will count in Integers into your float count. If you solely just want the number of float that is not integer, just take float count minus integer count.
Some tokens (like "50") are parseable both as integer and float. Your code gives both of them a chance, even though your intention is to only count each token as one type or the other (so count "50" as an integer, not as a float).
A simple fix could be to modify your float check to be:
make sure that i can pass Float.parseFloat(), and
confirm that i contains a decimal point
That code edit could look like this:
Float.parseFloat(i);
if (i.contains(".")) {
counter++;
continue;
}
Or, as a more involved alternative, instead of checking all input tokens for floats, then re-checking all input tokens for integers, I would take a different approach.
First, I would change the code to stop checking the entire input string repeatedly. This is helpful for 2nd part below, but also cleans up an unnecessary inefficiency of re-checking tokens even if you've already identified their data type. If you had a large number of tokens, it's wasteful to try parsing all of them as float, then try all of them as integer, then try a third time to count plain strings.
Second, since you would be checking (and counting) each token only one time, you could:
check for integer (before float) – if it passes Integer.parseInt(), increment that counter and move on to the next token
if it doesn't parse as integer, make an attempt to parse that token as float – just Float.parseFloat() without looking for decimal; if it worked then bump counter, move to next token
if it doesn't parse as integer or float, you know it's a String so simply bump the counter, then next token
As others have already said, since int is a subset of float, you can always parse a string representing an int as a float, while the opposite is not true. In fact, if the parsing string contains a decimal separator and you attempt to parse it as an int, you'll get a NumberFormatException.
However, you could use this behavior to your advantage and try to parse each string to the data type with minimal representation (int) and gradually increasing it as the parsing fails, until you reach the most generic representation (String). In your case, you could start to parse each string to int, if it fails proceed to float and ultimately to String if the float parsing doesn't work either.
Here is a possible implementation:
public class Main {
public static void main(String[] args) {
countTypesInString();
}
public static void countTypesInString() {
String str = "Hello my 50 name 4.5 is James, I 20 years old and i have 5.7 coins";
String[] vetStr = str.split("\\s+");
List<Integer> listInt = new ArrayList<>();
List<Float> listFloat = new ArrayList<>();
List<String> listStr = new ArrayList<>();
for (String s : vetStr) {
try {
listInt.add(Integer.parseInt(s));
} catch (NumberFormatException exInt) {
try {
listFloat.add(Float.parseFloat(s));
} catch (NumberFormatException exFloat) {
listStr.add(s);
}
}
}
System.out.println("Number of ints: " + listInt.size() + " => " + listInt);
System.out.println("Number of floats: " + listFloat.size() + " => " + listFloat);
System.out.println("Number of strings: " + listStr.size() + " => " + listStr);
}
}
Output
Number of ints: 2 => [50, 20]
Number of floats: 2 => [4.5, 5.7]
Number of strings: 12 => [Hello, my, name, is, James,, I, years, old, and, i, have, coins]
Side note: for real number representation, the double type is a better choice. In fact, by default Java treats every literal representing a real number as a double rather than a float. In the snippet above I've kept using float to maintain my code as close as possible to the original.
I have the following code where I need to print value up to two decimal places removing the dot(.) from the number.
How ever sometimes it print up to two and sometimes up to three places off decimal.
public class CheckSubString3 {
public static void main(String[] args) {
Double[] d={134344.00d,234434.08d,234434.02d};
for(int i=0; i<d.length; i++){
System.out.println((d[i])*(25)/100);
System.out.println(parseLonggetFormattedAmount((d[i])*(25)/100));
System.out.println();
}
}
private static String parseLonggetFormattedAmount(double d) {
DecimalFormat format = (DecimalFormat) NumberFormat
.getInstance(new Locale("en", "gb"));
format.setMinimumFractionDigits(2);
FieldPosition f = new FieldPosition(0);
StringBuffer s = new StringBuffer();
String value = format.format(d, s, f).toString().replace(',', ' ')
.replace('.', ' ');
return value.replaceAll(" ","");
}
}
Below is the output:
original value 33586.0
required value 3358600
original value 58608.52
required value 5860852
original value 58608.505
required value 58608505// This line is giving upto 3 places of decimal
According to the NumberFormat documentation, you could use setMaximumFractionDigits(int newValue)
Sets the maximum number of digits allowed in the fraction portion of a number.
just put it in your function parseLonggetFormattedAmount(double d):
format.setMaximumFractionDigits(2);
It seems you simply want to multiply the doubles by 100 and round to the nearest integer. So your method could be written:
private static String parseLonggetFormattedAmount(double d) {
return String.valueOf(Math.round(d * 100));
}
Which outputs:
3358600
5860852
5860851
I have the below requirement:
input String = "1.00000" should be converted to int ( because actually no fraction at all )
input String = "1" should be converted to int 1
however, input String ="1.0001" should be an Exception (because has fraction )
Previously I was assuming Integer.valueOf("1.00000") should return an integer.However it returns NumberFormatException.
any Java library that can solve this, or at least can check if 1.0000 is actually an integer so I can safely parse as Double and cast it to int?
BigDecimal class
Java itself has a library that does exactly this: BigDecimal
Example:
private static int parse(String input) throws ArithmeticException {
return new BigDecimal(input).intValueExact();
}
The intValueExact method throws an ArithmeticException if the BigDecimal object has a non-zero fractional part.
One way to tackle the problem is, you can use regex to first ensure that the input exactly matches the format of a number with fractional part being optional and if at all then all being zeroes and if yes, then go ahead and parse it else throw Exception or whatever you want to do. Check this Java code,
List<String> list = Arrays.asList("1.00000","1","1.0001");
Pattern intPat = Pattern.compile("(\\d+)(\\.0+)?");
list.forEach(x -> {
Matcher m = intPat.matcher(x);
if (m.matches()) {
int num = Integer.parseInt(m.group(1));
System.out.println(num);
} else {
System.out.println(x +" is not a pure Integer"); // Throw exception or whatever you like
}
});
Outputs,
1
1
1.0001 is not an Integer
Also, as long as the numbers you are working with are confined within integer range, its all good but to ensure the numbers don't cross integer limit, you may want to use a different quantifier.
Another alternate simpler solution you can go for is, parse the number as double and compare it with its int form and if both are equal then it is a pure integer else not. I'll prefer this than my first solution using regex. Java code,
List<String> list = Arrays.asList("1.00000","1","1.0001");
list.forEach(x -> {
double num = Double.parseDouble(x);
if (num == (int)num) {
System.out.println((int)num);
} else {
System.out.println(x + " is not a pure Integer");
}
Prints,
1
1
1.0001 is not a pure Integer
I need to print a Double as a String but I don't know how many decimal places there will be and I have to be prepared for as many as possible. Right, now I'm using this ugly solution:
Double dubs = 0.000157;
NumberFormat formatter = new DecimalFormat(
"##.########################################################################################");
System.out.println(formatter.format(dubs));
You can do this with no conversion:
public class codesnippets {
public static void main(String[] args)
{
Double dubs = 0.000157;
System.out.printf("%f", dubs);
}
}
You can also use
Double dubs = 0.000157;
String dubs_format = String.format("%f", dubs);
System.out.println(dubs);
EDIT: Apparently there is a precision loss when using "%f" as a format string. If this is the case for you, use "%.10f"
Try here man. I think this is what you're saying. The answer given at the bottom.
Number of decimal digits in a double
Here is what I meant.
double d= 234.12413;
String text = Double.toString(Math.abs(d));
int integerPlaces = text.indexOf('.');
int decimalPlaces = text.length() - integerPlaces - 1;
Then you just concatenate them
String xmlString = integerPlaces.toString() + "." + decimalPlaces.toString();
This seemed to work based on Steampunkery's idea. The catch was that I needed an actual String which I realize I wasn't clear on.
String dubString= String.format("%f", dubs);
System.out.println(dubString);
In Europe decimals are separated with ',' and we use optional '.' to separate thousands. I allow currency values with:
US-style 123,456.78 notation
European-style 123.456,78 notation
I use the next regular expression (from RegexBuddy library) to validate the input. I allow optional two-digits fractions and optional thousands separators.
^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\.[0-9]{0,2})?|(?:\.[0-9]{3})*(?:,[0-9]{0,2})?)$
I would like to parse a currency string to a float. For example
123,456.78 should be stored as 123456.78
123.456,78 should be stored as 123456.78
123.45 should be stored as 123.45
1.234 should be stored as 1234
12.34 should be stored as 12.34
and so on...
Is there an easy way to do this in Java?
public float currencyToFloat(String currency) {
// transform and return as float
}
Use BigDecimal instead of Float
Thanks to everyone for the great answers. I have changed my code to use BigDecimal instead of float. I will keep previous part of this question with float to prevent people from doing the same mistakes I was gonna do.
Solution
The next code shows a function which transforms from US and EU currency to a string accepted by BigDecimal(String) constructor. That it is to say a string with no thousand separator and a point for fractions.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestUSAndEUCurrency {
public static void main(String[] args) throws Exception {
test("123,456.78","123456.78");
test("123.456,78","123456.78");
test("123.45","123.45");
test("1.234","1234");
test("12","12");
test("12.1","12.1");
test("1.13","1.13");
test("1.1","1.1");
test("1,2","1.2");
test("1","1");
}
public static void test(String value, String expected_output) throws Exception {
String output = currencyToBigDecimalFormat(value);
if(!output.equals(expected_output)) {
System.out.println("ERROR expected: " + expected_output + " output " + output);
}
}
public static String currencyToBigDecimalFormat(String currency) throws Exception {
if(!doesMatch(currency,"^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\\.[0-9]{0,2})?|(?:\\.[0-9]{3})*(?:,[0-9]{0,2})?)$"))
throw new Exception("Currency in wrong format " + currency);
// Replace all dots with commas
currency = currency.replaceAll("\\.", ",");
// If fractions exist, the separator must be a .
if(currency.length()>=3) {
char[] chars = currency.toCharArray();
if(chars[chars.length-2] == ',') {
chars[chars.length-2] = '.';
} else if(chars[chars.length-3] == ',') {
chars[chars.length-3] = '.';
}
currency = new String(chars);
}
// Remove all commas
return currency.replaceAll(",", "");
}
public static boolean doesMatch(String s, String pattern) {
try {
Pattern patt = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
Matcher matcher = patt.matcher(s);
return matcher.matches();
} catch (RuntimeException e) {
return false;
}
}
}
To answer a slightly different question: don't use the float type to represent currency values. It will bite you. Use a base-10 type instead, like BigDecimal, or an integer type like int or long (representing the quantum of your value - penny, for example, in US currency).
You will not be able to store an exact value - 123.45, say, as a float, and mathematical operations on that value (such as multiplication by a tax percentage) will produce rounding errors.
Example from that page:
float a = 8250325.12f;
float b = 4321456.31f;
float c = a + b;
System.out.println(NumberFormat.getCurrencyInstance().format(c));
// prints $12,571,782.00 (wrong)
BigDecimal a1 = new BigDecimal("8250325.12");
BigDecimal b1 = new BigDecimal("4321456.31");
BigDecimal c1 = a1.add(b1);
System.out.println(NumberFormat.getCurrencyInstance().format(c1));
// prints $12,571,781.43 (right)
You don't want to muck with errors when it comes to money.
With respect to the original question, I haven't touched Java in a little while, but I know that I'd like to stay away from regex to do this kind of work. I see this recommended; it may help you. Not tested; caveat developer.
try {
String string = NumberFormat.getCurrencyInstance(Locale.GERMANY)
.format(123.45);
Number number = NumberFormat.getCurrencyInstance(locale)
.parse("$123.45");
// 123.45
if (number instanceof Long) {
// Long value
} else {
// too large for long - may want to handle as error
}
} catch (ParseException e) {
// handle
}
Look for a locale with rules that match what you expect to see. If you can't find one, use multiple sequentially, or create your own custom NumberFormat.
I'd also consider forcing users to enter values in a single, canonical format. 123.45 and 123.456 look way too similar for my tastes, and by your rules would result in values that differ by a factor of 1000. This is how millions are lost.
As a generalized solution you can try
char[] chars = currency.toCharArray();
chars[currency.lastIndexOf(',')] = '.';
currency = new String(chars);
instead of
if(currency.length()>=3) {
char[] chars = currency.toCharArray();
if(chars[chars.length-2] == ',') {
chars[chars.length-2] = '.';
} else if(chars[chars.length-3] == ',') {
chars[chars.length-3] = '.';
}
currency = new String(chars);
}
so that fractional part can be of any length.
Try this.............
Locale slLocale = new Locale("de","DE");
NumberFormat nf5 = NumberFormat.getInstance(slLocale);
if(nf5 instanceof DecimalFormat) {
DecimalFormat df5 = (DecimalFormat)nf5;
try {
DecimalFormatSymbols decimalFormatSymbols = DecimalFormatSymbols.getInstance(slLocale);
decimalFormatSymbols.setGroupingSeparator('.');
decimalFormatSymbols.setDecimalSeparator(',');
df5.setDecimalFormatSymbols(decimalFormatSymbols);
df5.setParseBigDecimal(true);
ParsePosition pPosition = new ParsePosition(0);
BigDecimal n = (BigDecimal)df5.parseObject("3.321.234,56", pPosition);
System.out.println(n);
}catch(Exception exp) {
exp.printStackTrace();
}
}
A quick a dirty hack could be:
String input = input.replaceAll("\.,",""); // remove *any* , or .
long amount = Long.parseLong(input);
BigDecimal bd = BigDecimal.valueOf(amount).movePointLeft(2);
//then you could use:
bd.floatValue();
//but I would seriously recommended that you don't use floats for monetary amounts.
Note this will only work if the input is in the form ###.00, ie with exactly 2 decimal places. For example input == "10,022" will break this rather naive code.
Alternative is to use the BigDecimal(String) constructor, but you'll need to convert those euro style numbers to use '.' as the decimal separator, in addition to removing the thousand separators for both.