Convert Float To String With Commas No Rounding Or Decimal Changes - java

I am trying to convert a float to a String and insert commas into the resulting String. I don't want to add/remove any zeroes, change the precision of the float, or do any kind of rounding. I want the String result to have the exact same digits as the original float, just with commas added. A locale agnostic solution would be preferred.
What I need:
public String convertFloat(float number) {
// return converted String with commas and no rounding or extra digits
}
Some input/output examples:
Given float: 1500
Result: "1,500"
Given float: 0.00210014
Result: "0.00210014"
Given float: 168874.00210014
Result: "168,874.00210014"
Given float: 168874.01
Result: "168,874.01"
Things I have tried:
String.valueOf(168874.00210014f) // Does not work for me because the result does not contain commas
String.format("%,f", 10.2f) // Does not work for me because it inserts a bunch of zeroes on the end
// The below does not work for me because the precision gets thrown off and the result ends up being: 14.1999998093 When it should be just: 14.2
NumberFormat f = NumberFormat.getInstance();
f.setMaximumFractionDigits(10);
System.out.println(f.format(14.2f));
// Result: 14.1999998093
// The below does not work for me because a bunch of random extra digits get thrown onto the end
DecimalFormat f = new DecimalFormat("#,###.##########");
System.out.println(f.format(100514.2f));
// Result: 100,514.203125
// The below does not work for me because it rounds to 2 decimal places
DecimalFormat f = new DecimalFormat("#,###.00");
System.out.println(f.format(100514.21351f));
// Result: 100,514.203125
// Does not work for me because it rounds to 2 decimal places.
String s = String.format("%,.2f", 10.2629f)
What I am trying to do seems so simple. How can I get the exact same digits just with commas added in the resulting string?

It's important to realize that a float has about 7 digits of decimal precision -- about, because decimal numbers can't be represented precisely.
Your example value of 100514.213512345f won't ever come back out the same way you put it in because the original value would necessarily have been truncated at a value somewhere in the neighborhood of 100514.2
I know you don't want any rounding, but it's the nature of floating point math on computers. Even if you use double precision, you just make the rounding smaller -- the issue of rounding doesn't go away.

By default its 6 digits.
There are few pointers that I found:-
Float is distorting the value after decimal while double is not. Hence, would recommend using double.
It's impossible to show as many as digits after decimal as there are in original number. Hence below is a workaround:
String string = String.format("%,.6654f", Math.abs(n)).replaceAll("0*$", "")
n is a double number not a float.
I have used 6654 as random max decimal digits that you could have in your number increase it if you need to.

This is kind of hack but you can replace preceding zeros
String.format("%,f", 10.2f).replaceAll("0*$","")
As for precision with big numbers you should use BigDecimal
Additionally you can remove last dot if its round number
String.format("%,f", new BigDecimal(100010f)).replaceAll("0*$","").replaceAll("\\.$","")

OP here,
None of these answers really worked for me. Turns out that in my case converting to double was not possible. So I decided to sacrifice the commas and just go with String.valueOf() approach

Acknowledging what others have already posted regarding the limited about of digits allowed in a float, here's a version that should work when you are within the limit and won't cut out consecutive 0s if they properly belong to the float. We're basically just splitting the input into 2 substrings and adding the comma formatting to the first half.
String input = String.valueOf(number);
int decimalIndex = input.indexOf(".");
String firstHalf = input.substring(0, decimalIndex);
String secondHalf = input.substring(decimalIndex, input.length());
String commas = String.format("%,d", Integer.parseInt(firstHalf));
return commas + secondHalf;
If you want to retain more precision then please use doubles instead of floats.

Related

Loss of precision in decimal display of double

Why is there a discrepancy in the display of the following value?
double x = (double)988530483551494912L;
System.out.printf("%f%n", x); -> 988530483551494910.000000
System.out.println(Double.toString(x)); -> 9.8853048355149491E17
System.out.println(new BigDecimal(x)); -> 988530483551494912
As you can see, both toString() and the %f conversion lose the precision of the last digit. However, we can see that the last digit is actually precise, because the BigDecimal conversion preserves it.
Thanks to #user16320675's comment, I'm answering my own question. The reason is that the number 988530483551494912L has precision beyond the limit of the double type's precision, and Double.toString() (and similarly %f) will, as per documentation, only use the minimum number of significant digits required to distinguish a double number from adjacent numbers. Adjacent numbers are those that have the smallest representable difference from the original, on either side of it.
This can be demonstrated using Math.nextAfter to show the adjacent numbers:
import static java.lang.Math.nextAfter;
double x = (double)988530483551494912;
System.out.println(nextAfter(x, Double.MIN_VALUE)); ==> 9.8853048355149478E17
System.out.println(x); ==> 9.8853048355149491E17
System.out.println(nextAfter(x, Double.MAX_VALUE)); ==> 9.8853048355149504E17
So, as we can see, there is no point in adding any more significant figures because this string representation already has enough digits to distinguish the number from adjacent values.
However, a question still remains: it shows 17 significant figures, but 16 would be sufficient. I'm not sure why it issues an extra final digit.

Converting String to BigDecimal with leading zeros

I am trying to convert an inputstream to objects and am having trouble with converting the below string to BigDecimal. I get 87.00 as the 0's are ignored. I am experimenting with DecimalFormat. Any help is appreciated. Thanks!
E.g. 0087 has to be converted to 00.87
You seem to indicate in comments that the initial string, "0087", is a fixed-point representation with two decimal places, there therefore being an implicit decimal point before the last two digits. There are several ways that you could convert that to a corresponding BigDecimal, but myself, I would go with this:
BigDecimal result = BigDecimal.valueOf(Long.parseLong("0087"), 2);
The key here is to understand that BigDecimals have two characteristic properties: an arbitrary-length sequence of decimal digits, and a scale conveying the place value of the least-significant digit, in the form of the number of digits to the right of the decimal point. The particular factory method demonstrated above accepts those as separate arguments, though it only works if the digit string is short enough to be represented as a long. The 2 corresponds directly to the number of (implicitly) fractional digits in your input.
Outputting the resulting BigDecimal as "00.87" instead of "0.87" is a separate issue, but doable, if it's really something you want.
Try this code
String str="0087";
int pos=str.lastIndexOf("0");
String resultat=str.substring(0,pos+1);
resultat+=".";
resultat+=str.substring(pos+1);
System.out.println(resultat);
new BigDecimal(resultat);

Java rounding a double truncates zeroes

I have below logic that rounds a double value to 2 decimal places:
public double round(double value, int places) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
It is working for most of the cases but fails to round the result to 2 decimal places in some cases, below is an example for it.
If I call this method using code round(12.503, 2), I need the result as 12.50 because I need result in 2 decimal places, but I am getting output as 12.5
Please help me how to fix this case.
A double in Java represents a mathematical number where 12.50 is the same number as 12.5. How many digits of a number are shown is a concern of converting it to a string, not of the number itself.
So better do the rounding when you convert the number to a string for output, e.g.:
System.out.printf("%5.2f", value);
You are not getting the result as 12.5.
You are receiving back a double.
Then, you have chosen some arbitrary method of displaying that double, (which you have told us nothing about,) and based on the results of applying that method you think that its value is 12.5.
You see, the thing with doubles is that they cannot be thought of as having a fixed number of decimal digits. (Or, more accurately, the number of decimal digits that they have is so huge, that nobody ever wants to see them all.) So, in all likelihood the actual value of the double that you receive, without any bias introduced by various methods of displaying it, is something akin to 12.5000000... But you need to choose the right method of displaying it in order to see what it is. If the method that you chose simply strips trailing zeros, then you may be left with the impression that you are missing a trailing zero. Or 10 trailing zeros.
So, you need to convert it back to BigDecimal before you can make any assumptions as to what result you are getting.

Convert double to double with one decimal point and one decimal place?

I want to round any double to a double with the format of one decimal point and one decimal place so 29575.347434 would be 2.3.
Tried doing this with decimalFormat but when i try #.# i just get a string in the format of 29575.3 with a , and i have no idea idea how to cut off all decimal points while keeping my value a double.
You could get the number as String, take the first digit and the digit after '.'. For non-negative numbers that would be
String s = Double.toString(29575.347434);
double d = Double.parseDouble(s.charAt(0) + "." + s.charAt(s.indexOf('.') + 1));
System.out.println(d); // 2.3
If the number can be negative, you would have to correct the code for the possible minus sign.
You could accomplish this by using the modulo operator %.
It looks like your decimal formatting is working with #.#. That will give you the whole number and one decimal place. You can then do your number 29575.3 % 10 and get 5.3.
Try this code and see:
System.out.println(29575.3d % 10);
Try the following:
Number(parseFloat(29575.347434).toFixed(1))
You could also pass a string , because parseFloat() would convert it to number, then trunkate to wished decimal (output is string again), then convert back to decimal by function Number().
Works for me.

Java keep trailing 0 in float operations

the code:
Float f = Float.parseFloat("1.80");
System.out.println(f);
prints "1.8" on screen.
I need to keep the 0 in the float value (Float f) for some validation. How do I do this?
You are confusing a number value and its formatting. It is not possible to actually store 1.80 as a float, however it is possible to display the number as a formatted String which forces two decimal places. Your options are:
Keep the original String that the user entered, if the number of decimal places they gave
matters
Store the number as a float, but when displaying the number force it to display with two decimal places like this:
System.out.printf("%.2f\n", f);
That's simply a formatting issue:
System.out.printf("%.2f\n", f);
Floating point variables don't have decimal places. They have binary places.
1.8 and 1.80 are the same number, and they are represented the same way in a float or double.
If you want them presented with a certain number of decimal places, you have to convert to a decimal radix, via either BigDecimal or DecimalFormat, where you can control the number of decimal places.
In short the question doesn't really make sense as posed.

Categories