Java: public static final double can't be set to decimal fraction? - java

I have a config file which includes some factors I want to use for calculations.
public class Config {
public static final double factor = 67/300; // ~0,2233...
}
Im accessing the factors like this:
public class Calculate {
public static calc() {
...
result *= Config.factor;
...
When I do that Config.factor equals 0, so my result is 0, too. I don't have that problem if I set the factor to 0.2233, but that wouldn't be as accurate. Why doesn't setting it to 67/300 work?

Try this:
public static final double factor = 67/300d;
The problem is that 67 and 300 are integer literals, so the division ends up being an integer, which is 0. The d at the end of the number makes it a double literal, so the result of 67/300d is a double.
Note that in the previous code the double literal is 300d. You can also use 67d/300 or 67d/300d.

It should be something like below:
public static final double factor = 67d/300d;
If you don't append 'd' it will be treated as integer that is why you are getting ZERO.
int will be deafault choice. As per doc
For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else

When you enter 67/300, the compiler treats these as int rather than double. Therefore, when the division occurs, the result is floored to 0.
To avoid this, cast the numbers to double either by adding a d after each number (as described in the other answers) or a full type cast with (double).

Related

method is performing incorrect calculations on double argument

firstly, im sorry if this is a trivial question. I am a beginner and have been stuck on this for hours.
Below I have tried to create a unitizer method which has a series of if else statements. They are written in descending order, each time checking if a value can be divided by a given number, and if so, performing a division, rounding the value and adding an appropriate unit to the result.
in this question I have attempted to remove all unnecessary code, thus what i am presenting here is only a fragment of the unitizer method.
why is the unitizer method outputting values in hours, when the value should be in seconds?
For clarification, the expected value is ~ 4 seconds.
public class simplified
{
public static void main(String[] args)
{
int i = 5;
double n = Math.pow(2, (double) i);
System.out.println(a6(n)); // correctly displays the expected value.
System.out.println(unitizer(a6(n)));
}
public static double a6 (double n)
{
return Math.pow(2, n); // this value is in nanoseconds.
}
public static String unitizer (double x)
{
String time = "";
if (x/(60*60*1000*1000*1000) >= 1)
{
x = Math.round(x/(60*60*1000*1000*1000) * 100.0) / 100.0;
time = x + "hr ";
}
return time;
}
}
console output:
4.294967296E9
5.25hr
There is an int overflow at the expression 60*60*1000*1000*1000. This means, that the actual result 3,600,000,000,000 is too large to be stored as an int value and is therefore 'reduced' (mod 2^31) to 817,405,952.
This can be fixed by evaluating said expression in a 'larger' arithmetic, e.g. long. There is a nice little modifier, that will force exactly that:
60L*60*1000*1000*1000
^
In particular, it hints the compiler to interpret the preceding literal 60 as a long value and in consequence the whole calculation will be done in long arithmetic.
This modifier is by the way case-insensitive; however I prefer an upper-case L, because the lower-case letter l can easily be mistaken by the number 1.
With this change, the code will not enter the if-statement, because the value x is not larger than one hour. Most probably the omitted code of unitizer will deal with this case.
On a last side note, java has an in-built TimeUnit enum, which can do these conversions, too. However, it does so in long arithmetic and not in double arithmetic as it is required for this specific question.

Java Ceil Weirdness

Why does this output 0 instead of 1?
System.out.println((int) (Math.ceil(1/2)));
While this one correct outputs 1
System.out.println((int) (Math.ceil((double) 1/ (double) 2)));
Shouldn't Math.ceil(double) automatically type cast the 1/2 to double?
Math.ceil does, indeed, cast the integer to a double. But it only does so after the integer operation has been performed. This is the order of operations:
int a = 1;
int b = 2;
int c = a / b; // now equals 0, because it's an integer operation.
double d = (double)c; // now it's a double - but equals 0.0.
double e = Math.ceil(d); // still 0.0.
You're thinking of 1/2 as a fraction, but it's not - it's an expression of two ints and an operator that has to be resolved before its value can be used in further expressions.
Explicit casting always require (datatype) to be mentioned. Here 1 and 2 represents itself as int and to cast from int to double explicit casting will be introduced. Whenever casting is preformed from lower to higher datatypes explicit casting should be imposed. See example below;
public class MainClass{
public static void main(String[] argv){
int a = 100;
long b = a; // Implicit cast, an int value always fits in a long
}
}
An explicit casts looks like this:
public class MainClass{
public static void main(String[] argv){
float a = 100.001f;
int b = (int)a; // Explicit cast, the float could lose info
}
}
Code Snippet: Source
The first thing which happens when that line is executed, is that the division 1/2 is resolved. This happens without any consideration for the method-call to Math.ceil it is embedded in.
The literals 1 and 2 are integers. When you perform a division with only integers as arguments, an integer division is performed, which always rounds down. So the term gets resolved to the int value 0. Math.ceil() only accepts type double, but that's not a problem because Java can perform the conversion automatically and turn the int 0 to a double 0.0.
To perform an explicit floating point division, have one or both of the parameters to the division be floating point literals:
System.out.println((int) (Math.ceil(1.0/2.0)));

Typecasting in java: Integer and Double

Can someone explain how typecasting works in the line int y = (int) x;
Thank You
public class typecast
{
public static void main(String [] args)
{
double x=10.5;
int y=(int) x;
System.out.println("x="+x);
System.out.println("y="+y);
}
}
The type cast performs a narrowing type conversion. The exact conversion depends on the double value, as follows:
If it is within the range of int values, it is rounded towards zero.
If it outside of the range or is an "Inf" value, then the conversion gives Integer.MIN_VALUE or Integer.MAX_VALUE, depending on the sign.
If it is a "NaN" value, the conversion gives zero.
Reference: JLS 5.1.3
Note: "round towards zero" is defined as follows:
"The Java programming language uses round toward zero when converting a floating value to an integer (ยง5.1.3), which acts, in this case, as though the number were truncated, discarding the mantissa bits. Rounding toward zero chooses at its result the format's value closest to and no greater in magnitude than the infinitely precise result."
In this particular case, the code won't compile if you try and take a double (variable x) and assign it's value to an int (variable y). So you have to explicitly tell the compiler to cast (convert) the type from a double to an int. When it does that, in this particular case, I believe it drops the fractional part instead of rounding up/down. I could be wrong about that last point.

Java mistakes with numbers

I am trying to fix the following Java code,
I cannot figure out why the printout is still 5.
public class simpleMath
{
public static void main(String[] args)
{
int number=5;
half(number);
System.out.println("5 divided by 2 is: " + number);
}
private static double half(int number) {
number = number/2;
return number;
}
}
Because you're not re-assigning the returned value.
int number = 5;
number = half(number);
When you call the function, you're discarding its return value:
half(number);
You probably meant to write:
number = half(number);
Also, in Java, arguments are passed by value. This means that, even though you change number inside the function, the change does not propagate back to the caller.
There are several further problems:
Problem 1: The suggested change will store the result in number, which is an integer variable. Thus, the result of half() -- which is of type double -- will be truncated to an integer. To avoid the loss of precision, you either have to change number to be a floating-point variable, or store the result in a different variable of the appropriate type.
Problem 2: The following uses integer division:
number = number/2;
The result is truncated to an integer, i.e. 5 / 2 is 2. The latter is then converted to a double (2.0), which is what the function returns.
To fix, change the function like so:
private static double half(int number) {
return number / 2.0;
}
P.S. Floating-point numbers have a lot of properties that can be unintuitive. I recommend having a look at What Every Computer Scientist Should Know About Floating-Point Arithmetic.
You passing the primitive data type which is done by value. You need to give SOP in method half()
EDIT: Need to use the result returned by method half() by either assigning it to number or calling this method in SOP itself.
Why half(number) doesn't modify number declared in main() function? It is because you will pass the value of number to half() function to evaluate, i.e. you give a copy of value in number to half() function. Therefore, whatever half() function does to number will not get reflected back to number variable declared in main(). You need to assign the return value of half() to number in main() if you want to update its value.
There are other cases, such as variable shadowing, that I'm not going to talk in details, since it may confuses you.
It's because you're not assigning the return value of half() to number - it gets calculated but not used.
You need to say:
number = half(number);
The way you have it currently would only work if number was being passed by reference, not by value.
int number =5;
half(number);
Java doesn't support pass by reference. So In this case we are passing value that is 5 not reference of number.
So if we want to capture the changes then method call should be like this -
public class simpleMath
{
public static void main(String[] args)
{
int number =5;
number = half(number);
System.out.println(" 5 divided by 2 is:"+ number);
}
private static double half(int number) {
number = number/2;
return number;
}
}
First you need to be aware of what types you are assigning to your variables. You should change your code to look like this:
public class simpleMath
{
public static void main(String[] args)
{
double number = 5;
double answer = half(number);
System.out.println(" 5 divided by 2 is:"+ answer);
}
private static double half(double number) {
number = number/2.0;
return number;
}
}
See how I now use the returned value and how I divide by 2.0? these changes will give you the results you are looking for.

Java BigDecimal difference

I wanted to see if anyone can explain why the following code works with valueOf but not others.
import java.math.BigDecimal;
public class Change {
public static void main(String args[]) {
double a = 4.00d;
double b = 3.10d;
BigDecimal a1 = new BigDecimal(a);
BigDecimal b1 = new BigDecimal(b);
BigDecimal diff = a1.subtract(b1);
System.out.println("Double difference");
System.out.println(diff);
float c = 4.00f;
float d = 3.10f;
BigDecimal a2 = new BigDecimal(c);
BigDecimal b2 = new BigDecimal(d);
BigDecimal diff2 = a2.subtract(b2);
System.out.println("Float difference");
System.out.println(diff2);
System.out.println("Valueof Difference");
System.out.println(BigDecimal.valueOf(4.00).subtract(BigDecimal.valueOf(3.10)));
}
}
The output looks like:
>java Change
Double difference
0.899999999999999911182158029987476766109466552734375
Float difference
0.900000095367431640625
Valueof Difference
0.9
My question is: What does valueOf() do to get the precision?
Is there any other way of getting the correct result without rounding off to the 2 digits manually?
thanks,
Looking at the source code for BigDecimal, it does:
public static BigDecimal valueOf(double val) {
// Reminder: a zero double returns '0.0', so we cannot fastpath
// to use the constant ZERO. This might be important enough to
// justify a factory approach, a cache, or a few private
// constants, later.
return new BigDecimal(Double.toString(val));
}
From its JavaDoc:
Translates a double into a BigDecimal,
using the double's canonical string
representation provided by the
Double.toString(double) method.
Note: This is generally the preferred way to
convert a double (or float) into a
BigDecimal, as the value returned is
equal to that resulting from
constructing a BigDecimal from the
result of using
Double.toString(double).
Because of floating-point representation, a double value is not exactly what you set it as. However, during String representation, it rounds off what it displays. (All of the rules are on it's JavaDoc).
Furthermore, because of this rounding, if you did:
BigDecimal d = BigDecimal.valueOf(4.00000000000000000000000000000000001));
you would get the wrong value. (d == 4.0)
So, it's pretty much always better to initialize these with strings.
BigDecimal.valueOf(double) first does a conversion from double to String, then String to BigDecimal.
In the first case, you're starting with a double or float, converting to BigDecimal, calculating the difference. In the second case, you're starting with double or float, converting to a String, then converting to BigDecimal, then calculating the difference.
From the Javadocs:
public static BigDecimal valueOf(double val)
Translates a double into a BigDecimal,
using the double's canonical string
representation provided by the
Double.toString(double) method. Note:
This is generally the preferred way to
convert a double (or float) into a
BigDecimal, as the value returned is
equal to that resulting from
constructing a BigDecimal from the
result of using
Double.toString(double).
I think this answers both of your questions.
Cheers,
The valueOf works because it calls Double.toString. from the Javadoc:
public static BigDecimal valueOf(double val)
Translates a double into a BigDecimal, using the double's
canonical string representation
provided by the
Double.toString(double) method.
When you pass a double into the BigDecimal constructor, the constructor takes the floating-point value and reproduces it exactly. The toString code finds an approximation for the floating point value.
In case you didn't notice, using System.out.println() to show a floating point number doesn't show the same results as if you wrap the floating point number in a BigDecimal first (using the BigDecimal constructor that takes a double).

Categories

Resources