Why BigDecimal does not print 0.5000 in java? - java

I want to print 0.5000 value in java therefor I try BigDecimal for this purpose but when i divide i get 0.5 with red color.
Can i print 0.5000 using BigDecimal if not then why and why does 0.5 print in red font?
My code is:
static void plusMinus(int[] arr) {
Double n = 0.0, p = 0.0, z = 0.0;
for(int i = 0; i < arr.length; i++) {
if(arr[i] < 0) n++;
else if(arr[i] > 0) p++;
else z++;
}
n = BigDecimal.valueOf(n/arr.length).setScale(4,RoundingMode.HALF_UP).doubleValue();
p = BigDecimal.valueOf(p/arr.length).setScale(4,RoundingMode.HALF_UP).doubleValue();
z = BigDecimal.valueOf(z/arr.length).setScale(4,RoundingMode.HALF_UP).doubleValue();
System.err.println(p); // print:0.5 //(in red font)
System.out.println(n); // print:0.3333
System.out.println(z); // print:0.1667
}

n = BigDecimal.valueOf(n/arr.length).setScale(4,RoundingMode.HALF_UP).doubleValue();
The result of the right hand side is a double: and it gets autoboxed to a Double to assign it to the left hand side. When you print n, you're not printing a BigDecimal, but rather a Double.
There is no such thing as a Double (or a double) 0.5000 as distinct from a Double (or a double) 0.5. 0.5000 == 0.5: they are the same value.
Since there is no scale information stored in a Double (or a double), there is no way of knowing that you want 0.5000 as opposed to 0.5 or 0.500000000.....000.
If you want to print with a certain number of decimal places, either use a NumberFormatter of some flavour, or keep it as a BigDecimal.

Related

5.16 LAB: Adjust list by normalizing _ zybook - Java

5.16 LAB: Adjust list by normalizing
When analyzing data sets, such as data for human heights or for human weights, a common step is to adjust the data. This adjustment can be done by normalizing to values between 0 and 1, or throwing away outliers.
For this program, adjust the values by dividing all values by the largest value. The input begins with an integer indicating the number of floating-point values that follow. Assume that the list will always contain fewer than 20 floating-point values.
Output each floating-point value with two digits after the decimal point, which can be achieved as follows:
System.out.printf("%.2f", yourValue);
Ex: If the input is:
5 30.0 50.0 10.0 100.0 65.0
the output is:
0.30 0.50 0.10 1.00 0.65
The 5 indicates that there are five floating-point values in the list, namely 30.0, 50.0, 10.0, 100.0, and 65.0. 100.0 is the largest value in the list, so each value is divided by 100.0.
For coding simplicity, follow every output value by a space, including the last one.
I have been confused about how to do floating-point values in arrays and loops as in my book it never went over that.
Scanner scnr = new Scanner(System.in);
double numElements;
numElements = scnr.nextDouble();
double [] userList = new double [numElements];
int i;
double maxValue;
for (i = 0; i < userList.length; ++i) {
userList[i] = scnr.nextDouble();
}
maxValue = userList[i];
for (i = 0; i < userList.length; ++i) {
if (userList[i] > maxValue) {
maxValue = userList[i];
}
}
for (i = 0; i < userList.length; ++i) {
userList[i] = userList[i] / maxValue;
System.out.print(userList[i] + " ");
System.out.printf("%.2f", userList[i]);
}
}
}
It's outputting:
LabProgram.java:8: error: incompatible types: possible lossy conversion from double to int
double [] userList = new double [numElements];
I am confused about how to move forward, any help will be much appreciated!
Just change the data type of numElements to int and the scanner command to int as well
Like this:
int numElements = scnr.nextInt();

How do I round up a double to a certain amount of decimals

I want to call a function with a double parameter and an int precision.
This function would have to round that number with the precision number as decimals.
Example: function(1.23432, 4) would have to round that number up with 4 decimals (1.2343). Could anyone help me out with this?
BigDecimal is your friend when it comes to rounding numbers. You can specify a MathContext to explicitly set how you want you rounding to work, and then define the precision you want to use. If you still want a double at the end you can call BigDecimal.doubleValue()
Try this code
String result = String.format("%.2f", 10.0 / 3.0);
// result: "3.33"
First, you get 10precision, then you multiply it by your number, round it to an int and divide by 10precision:
public double round(double number, int precision) {
// 10 to the power of "precision"
double n = Math.pow(10.0, precision);
// multiply by "number" and cast to int (round it to nearest integer value)
int aux = (int) (n * number);
// divide it to get the result
return aux / n;
}
Then you call:
double result = round(1.23432, 4);
System.out.println(result); // 1.2343
Try this:
public String round(double value, int factor) {
double newFactor = convertFactor(factor);
//will convert the factor to a number round() can use
String newVal = Double.toString(Math.round(value / newFactor) * newFactor);
//the value gets rounded
return newVal = newVal.substring(0, Math.min(newVal.length(), factor + 2));
//Convert the result to a string and cut it
//important because a too high value of the factor or value would cause inaccuracies.
//factor + 2 because you convert the double into String, and you have to fill 0.0 out
//Math.min() handles an exception when the factor is higher than the string
}
public double convertFactor(double factor) {
double newFactor = 1;
for(int i = 0; i < factor; i++) {
newFactor /= 10;
//devide the newFactor as many times as the value of the factor isnt reached
}
return newFactor;
}
Use convertFactor() to convert your "normal" factor into a factor (called newFactor) the round() method can use.
The round() method calculates the value and convert it into a String which
the max. lengh of the factor.
Too high values of value and factor would cause inaccuracies, and this little inaccuracies get cutted to get rid of them.
Example code (for your example):
System.out.println("newFactor: " + convertFactor(4)); //only for test!
System.out.println("Rounded value: " + round(1.23432, 4));
//newFactor: 1.0E-4
//Rounded value: 1.2343

Java Double convert to Int round

I want to convert a double value to int when and only when 2 numbers after the dot are 0.
Example
double x = 25.001
You can use this :
double x = 25.001;
int i = (int) x;
System.out.println(x);//Input
if (x - i <= 0.01) {
x = (int) x;
}
System.out.println(x);//Output
RESULT
Input Output
25.001 25.0
25.011 25.011
If you want to use a second variable you can use :
int y = 0;
if (x - i <= 0.01) {
y = (int) x;
}
Note
But note, in case your input is not correct, you will always get 0, i like the first solution it is good then the second.
if(x-Integer.parseInt(x)>=0.001)
//Convert here
That rounded number you then cannot store in a double, as a double is always an approximation of a real value - of a series of a (negative) power of 2.
So you should go for BigDecimal as many do that want to do financial software.
If you did something like:
double adjustWhenCloseToInt(double x) {
long n = Math.round(x); // Could overflow for large doubles
if (Math.abs(x - n) < 0.01) {
x = n;
}
return x;
}
A simple
x = adjustWhenCloseToInt(x);
System.out.print(x);
Could still print 0.00000001 or such.
The solution there is
System.out.printf("%.2f", x);
Or better use a localized MessageFormat (thousand separators and such).
As floating point always bears rounding errors, I would in general go for BigDecimal, though it is a circumstantial class to use. Take care to use String constructors:
new BigDecimal("3.99");
As they then can maintain a precision of 2.

double takes the value NaN after 0/0

I have this class that works on pixels of a sequence of images
private int makeRSR(int x, int y)
{
double bRed = 0;double bGreen = 0; double bBlue = 0;
for(int k: sequence.keySet())
{
BufferedImage img = sequence.get(k);
for(int i=0; i<iteration; i++){
for(int j=0;j<spray_int; j++){
int dist= ((int)(dis_int*Math.random()));
double theta=((int)(361*Math.random())) ;
double inc_x=dist * Math.cos((theta*(Math.PI/180)));
double inc_y=dist * Math.sin((theta*(Math.PI/180)));
int row=Math.abs((int)(inc_y+y));
int column=Math.abs((int)(inc_x+x));
if(row<1 || column<1 || row>altI-1 || column>largI-1){
row=Math.abs((int) ((altI-1)*Math.random()));
column=Math.abs((int) ((largI-1)*Math.random()));
}
Color c = new Color(img.getRGB(column,row));
red.add(c.getRed());
green.add(c.getGreen());
blue.add(c.getBlue());
}
Color c = new Color(img.getRGB(x,y));
red.add(c.getRed());
green.add(c.getGreen());
blue.add(c.getBlue());
double maxR=max(red);
double maxG=max(green);
double maxB=max(blue);
bRed += ((((double)c.getRed()) / (maxR))*255.00);
bGreen += ((((double)c.getGreen()) / (maxG))*255.00);
bBlue += ((((double)c.getBlue()) / (maxB))*255.00);
red.clear();green.clear();blue.clear();
}
}
redValue=0;greenValue=0;blueValue=0;
redValue= (int) (bRed/(iteration*(sequence.size())));
greenValue= (int) (bGreen/(iteration*(sequence.size())));
blueValue=(int) (bBlue/(iteration*(sequence.size())));
bRed=0.0;bGreen=0.0;bBlue=0.0;
return new Color(redValue,greenValue,blueValue).getRGB();
}
the problem is that sometimes c.getRed() and maxR are both 0 (same for the other channels) and so bRed loses its content and take value NaN, and it never change. Is there an error, something I missed, or do I have to prevent the 0/0 by adding a check?
Thanks, Bye
Since 0/0 is an undefined number you need to decide how do you want do treat it.
Find out why you get both 0 in current and max red values and prevent it.
Set result of division to 0 (or any number you decide to get the expected result) if both c.getRed() and maxR are 0.
Because dividing by zero is an error, it results in NaN, which stands for Not a Number. Subsequent operations involving NaN will also result in NaN, that's why it's value never changes afterwards.
You should explicitly check for zero divident before division to prevent division by zero.

Java iterator in double value

I am trying to iterate the value of I from 1 to 0 or from 0 to 1. But I have got some problem.
Please check the following codes:
double i = 1.0;
loop{ // Just use a loop to iterate the i. This is just a pseudocode.
// We can use while-loop or for-loop or timer.
// (I know there is no keyword "loop" in java)
i -=0.1;
if( i == 0.0){
// stop the loop
}
}
In the above code, the loop will never stop because when the variable i will become 0.7000000001 when i = 0.8 - 0.1 during the loop. i will have lots of decimal number when i = 0.1 - 0.1. so it will never equal to 0.0.
I apologized if my description of my question is not clear enough for you.
This may be a very easy question for pro programmers. But I cannot figure it out. Please let me know what I have done wrong.
I would recommend BigDecimal usage.
I know BigDecimal is used in financial systems, and not Double or Float, to describe exact numbers with decimal dots (i.e - prices).
Read more here
Why don't you like to iterate from 1...10 and divide current value by 10?
Something like this:
for(int i = 0; i <= 10; i++) {
double value = (double) i / 10d;
}
Or if you don't void to have precision issues you can use BigDecimal:
BigDecimal value = BigDecimal.ZERO;
for(int i = 0; i <= 10; i++) {
value = value.add(BigDecimal.valueOf(0.1d));
double doubleVal = value.doubleValue();
}
Use integers for iteration and scale them appropriately.
i = 10;
while (i != 0)
{
double d = i / 10.0;
// do stuff with d
i--;
}
This will work even if the scale factor is not representable in decimal.
Using BigDecimal will only work with decimal fractions. If for example you want to iterate by steps of one third it won't work.

Categories

Resources