Round percentage value to nearest number - java

I wanted to convert a number which is in string format to a percentage value with one decimal point. Below is my sample input and expected output.
Expected results:
"0.0195" => "2.0%"
"0.0401" => "4.0%"
I know this may be a simple question but I am not able to find the exact solution for this using java APIs, I tried all the rounding modes present under RoundingMode enum, but no rounding mode gives my expected result. Could you please help, I may be missing something.
import java.math.RoundingMode;
import java.text.NumberFormat;
public class RoundingModeExample {
public static void main(String[] args) {
System.out.println(formatPercentage("0.0195") + "(expected 2.0%)");
System.out.println(formatPercentage("0.0401") + "(expected 4.0%)");
}
private static String formatPercentage(String number) {
String formattedValue = "";
NumberFormat numberFormat = NumberFormat.getPercentInstance();
numberFormat.setMinimumFractionDigits(1);
numberFormat.setRoundingMode(RoundingMode.HALF_UP);
try {
formattedValue = numberFormat.format(Double.valueOf(number));
} catch (NumberFormatException e) {
formattedValue = number;
}
return formattedValue;
}
}
Output of the above program:
1.9%(expected 2.0%)
4.0%(expected 4.0%)

The problem with 0.0195 is that there is no double precision number that is exactly mathematically equal to it. When you write 0.0195 in program source code or parse the string "0.0195" into double, the number you get is actually a little bit less. That's why the formatter rounds it to 1.9%.
You can get around this by not using the double data type at all:
formattedValue = numberFormat.format(new BigDecimal(number));

Related

How to show user defined digits after a decimal

I am trying to figure out how to show the correct number of digits after a decimal, based off a number passed into the method.
public static double chopDecimal(double value, int place)
{
int chopped;
//???
return chopped;
}
So if the value passed is 123.456789 and the place is 2, it should show 123.45.
The print statement is in another method.
System.out.println("***MyMath ChopDecimal Test***");
//Chop Decimal Test 1
if (MyMath.chopDecimal(123.456789, 2) == 123.45)
{
System.out.println("Chop Decimal Test 1 Passed");
}
else
{
System.out.printf("Chop Decimal Test 1 Failed. Your answer: %f Correct Answer: 123.45\n",
MyMath.chopDecimal(123.456789, 2));
}
//Chop Decimal Test 2
if (MyMath.chopDecimal(.98765, 4) == .9876)
{
System.out.println("Chop Decimal Test 2 Passed");
}
else
{
System.out.printf("Chop Decimal Test 2 Failed. Your answer: %f Correct Answer: .9876\n",
MyMath.chopDecimal(.98765, 4));
}
This is possible using java.text.NumberFormat, although when you wish to convert to String for 'showing' purposes.
To match your example though, I've converted it babck to a double:
public static double chopDecimal(double value, int place)
{
String chopped = NumberFormat.getInstance().setMaximumFractionDigits( place ).format( value );
return Double.valueOf( chopped );
}
I suggest you to use the java Rounding Mode.
Simple example:
public static void main(String[] args) {
System.out.println(chopDecimal(123.456789, 2));
}
public static String chopDecimal(double value, int place)
{
// Parameter is the pattern
DecimalFormat format = new DecimalFormat("0.00");
format.setRoundingMode(RoundingMode.HALF_UP);
return format.format(value);
}
This question is duplicated:
How to round a number to n decimal places in Java
Reference:
Oracle Documentation
All of the answers above are pretty great, but if this for something you need to be able to explain, I wrote the segment of code below with all pretty basic tools of programming. Study this process below, it's not always about the solution, more so about can you come up with a solution. Always keep that in mind when solving any problem. There is always time later to improve your solution.
public static void main(String[] args) {
chopDecimal(123.456789,2);
}
public static double chopDecimal(double value, int place)
{
String valToStr = Double.toString(value);
int decimal=0;
for(int i = 0; i < valToStr.length(); i++)
{
if(valToStr.charAt(i) == '.')
{
decimal = valToStr.indexOf(valToStr.charAt(i));
System.out.println(decimal);
break;
}
}
String newNum = valToStr.substring(0,(++decimal+place));
System.out.println(newNum);
double chopped = Double.parseDouble(newNum);
return chopped;
}
}
Let me know if you have any questions.
You can use BigDecimal and setScale:
double chopped = BigDecimal
.valueOf(value)
.setScale(place, RoundingMode.DOWN)
.doubleValue()

How do I fix the error of NumberFormatException everytime I run the program?

I have to create a love calculator object for my computer science class.
However, every time I compile and run the program I keep ending up with the error:
java.lang.NumberFormatException:
For input string: "70.78%" (in sun.misc.FloatingDecimal)
My code for the method:
public double calculate()
{
double value1;
double value2;
double sqrt1;
double sqrt2;
double relationship;
sqrt1 = Math.sqrt(name1.length());
sqrt2 = Math.sqrt(name2.length());
value1 = (Math.pow(name1.length(), 3)/(Math.random()+0.1))* sqrt1;
value2 = (Math.pow(name2.length(), 3)/(Math.random()+0.1))* sqrt2;
if(value1 > value2)
{
relationship = value2 / value1;
}
else
{
relationship = value1 / value2;
}
NumberFormat nf = NumberFormat.getPercentInstance();
nf.setMinimumFractionDigits(2);
return Double.parseDouble(nf.format(relationship));
}
I attempted to convert it to a float. I tried to separate it by declaring and initializing another double variable and returning that instead but they didn't work. I looked up solutions and most said to use a try and catch but I don't understand how that would work (since I just began the class and am a beginner).
How would I use a try and catch for this situation?
NumberFormat is meant to create a human readable string. 70.78% isn't a number. 70.78 is, but with the percent sign, it's a string. It seems like what you're trying to do is use the number formatting functionality to round the number. This question has some suggestions for how to properly round a number and keep it as a number.
To answer your other question, the proper way to use a try/catch would be like this:
double result;
try{
result = Double.parseDouble(nf.format(relationship));
}catch(NumberFormatException e){
e.printStackTrace();
result = 0.0;
}
return result;
But the only thing that will do is cause your program to not crash and you'll always get 0.0 returned from the calculate() method. Instead you need to fix the source of the exception.
As you see the exception stacktrace, the exception is caused by string 70.78%. This is because it has a symbol where Double.parseDouble() is expecting a string in format of double value representation like 70.78. If you are looking for an output like 70.78% and if the value is correct, you may return nf.format(relationship) and change your return type of calculate to String.
Update
The following values are valid to be parsed as double: "1.2", "1", ".2", "0.2", "1.2D", "1.", to say a valid number representation holdable by the datatype.

Java - Is it possible to figure out the DecimalFormat of a string

I am trying to figure out how to, given a decimal through a String calculate the number of significant digits so that I can do a calculation to the decimal and print the result with the same number of significant digits. Here's an SSCCE:
import java.text.DecimalFormat;
import java.text.ParseException;
public class Test {
public static void main(String[] args) {
try {
DecimalFormat df = new DecimalFormat();
String decimal1 = "54.60"; // Decimal is input as a string with a specific number of significant digits.
double d = df.parse(decimal1).doubleValue();
d = d * -1; // Multiply the decimal by -1 (this is why we parsed it, so we could do a calculatin).
System.out.println(df.format(d)); // I need to print this with the same # of significant digits.
} catch (ParseException e) {
e.printStackTrace();
}
}
}
I know DecimalFormat is to 1) tell the program how you intend your decimal to be displayed (format()) and 2) to tell the program what format to expect a String-represented decimal to be in (parse()). But, is there a way to DEDUCE the DecimalFormat from a parsed string and then use that same DecimalFormat to output a number?
Use BigDecimal:
String decimal1 = "54.60";
BigDecimal bigDecimal = new BigDecimal(decimal1);
BigDecimal negative = bigDecimal.negate(); // negate keeps scale
System.out.println(negative);
Or the short version:
System.out.println((new BigDecimal(decimal1)).negate());
Find it via String.indexOf('.').
public int findDecimalPlaces (String input) {
int dot = input.indexOf('.');
if (dot < 0)
return 0;
return input.length() - dot - 1;
}
You can also configure a DecimalFormat/ NumberFormat via setMinimumFractionDigits() and setMaximumFractionDigits() to set an output format, rather than having to build the pattern as a string.
int sigFigs = decimal1.split("\\.")[1].length();
Computing the length of the string to the right of the decimal is probably the easiest method of achieving your goal.
If you want decimal places, you can't use floating-point in the first place, as FP doesn't have them: FP has binary places. Use BigDecimal, and construct it directly from the String. I don't see why you need a DecimalFormat object at all.
You could convert a number string to a format string using regex:
String format = num.replaceAll("^\\d*", "#").replaceAll("\\d", "0");
eg "123.45" --> "#.00" and "123" --> "#"
Then use the result as the pattern for a DecimalFormat
Not only does it work, it's only one line.

Is it normal that is not rounding while parsing? NumberFormat

Why does it not round in the parsing process?
NumberFormat format = NumberFormat.getInstance();
System.out.println(format.getMaximumFractionDigits());// 3
System.out.println(format.getRoundingMode());// half even
Double dob = (Double)format.parse("1212.35656");
System.out.println(dob);// output is 1212.35656
The digit counts are only used for formatting. When you parse a number you always get the number that best matches the input, even if it has more digits than the NumberFormat would use to format.
To parse a number from a string and then round to a given number of fractional digits you can use BigDecimal from the java.math package:
BigDecimal bd = BigDecimal("1212.35656");
double dob = bd.setScale(3, RoundingMode.HALF_EVEN).doubleValue();
To obtain what you desire you need to call the formatter metod of the implementation NumberFormat loaded (in your case DecimalFromat); i just added the needed lines at the end and wrapped in a main:
import java.text.NumberFormat;
public class NumberFormatRounding {
public static void main(String[] args) throws Exception{
NumberFormat formatter = NumberFormat.getInstance();
System.out.println(formatter.getMaximumFractionDigits());// 3
System.out.println(formatter.getRoundingMode());// half even
Double dob = (Double) formatter.parse("1212.35656");
System.out.println(dob);// output is 1212.35656
String formattedDob = formatter.format(dob.doubleValue());
System.out.println(formattedDob);// output is 1212.357
}
}
Note that the formattedDob is a String

Convert Double to String value preserving every digit

How do I convert a double value with 10 digits for e.g 9.01236789E9 into a string 9012367890 without terminating any of its digits ?
I tried 9.01236789E9 * Math.pow(10,9) but the result is still double "9.01236789E18"
double d = 9.01236789E9;
System.out.println(BigDecimal.valueOf(d).toPlainString());
While 10 digits should be preservable with no problems, if you're interested in the actual digits used, you should probably be using BigDecimal instead.
If you really want to format a double without using scientific notation, you should be able to just use NumberFormat to do that or (as of Java 6) the simple string formatting APIs:
import java.text.*;
public class Test
{
public static void main(String[] args)
{
double value = 9.01236789E9;
String text = String.format("%.0f", value);
System.out.println(text); // 9012367890
NumberFormat format = NumberFormat.getNumberInstance();
format.setMaximumFractionDigits(0);
format.setGroupingUsed(false);
System.out.println(format.format(value)); // 9012367890
}
}
Try String.format("%20.0f", 9.01236789E9)
Note though it's never an exact value, so "preserving every digit" doesn't really make sense.
You can use it.
String doubleString = Double.toString(inValue)
inValue -----> Described by you.to what position you want to Change double to a string.
In this case, you can also do
double value = 9.01236789E9;
System.out.println((long) value); // prints 9012367890

Categories