How did a float turn into a double here? - java

Edit: As always, great answer in under 5 minutes :) Turns out if I make a tiny change - make the F capital in "float", I'll get the output I expected.
class NumberMachine{
public static void main(String [] args) {
Integer wi1 = new Integer("420");
int i = 101;
Integer wi2 = i*420/101;
if(wi1 == wi2) System.out.print(" ==");
if(wi1.equals(wi2)) System.out.print(" equal");
float f = 1.23f; //if this were Float f..., it'd print Float, not double.
new NumberMachine().printIt(f);
}
void printIt(Float f){
System.out.println(" Float");
}
void printIt(double d){
System.out.println(" double");
}
}
The output is equal double, which makes no sense to me. I expected equal Float. If I comment out the 2nd printIt, then that's indeed the output. I just don't know why, when faced with a choice between the two printIt, the compiler ignored the one whose parameter matched perfectly.

You get the result you do because boxing/unboxing was added late in Java's life and it was required that pre-existing code not be changed by the addition of the feature. So when you pass in a primitive float to printIt, it gets coerced to a primitive double, because the alternative would mean old (pre-JDK1.4) code would act differently, which was an unacceptable possibility for Sun.
Basically, think if this was pre-JDK1.4 code where boxing was not an alternative, no way could the primitive double get coerced to a java.lang.Float. Adding boxing can't be allowed to break that.
Reading the question it occurs to me from how you word it you may not see the difference between Float and float, because you refer to the change from capital F to lowercase F as a tiny change, when it really isn't so tiny. The lowercase version refers to a primitive numeric type, the uppercase version refers to an object that wraps the primitive numeric type, in order to allow numeric stuff to be used in general purpose things like collections. Prior to JDK1.4 if you wanted to do something like this you had to manually write a line like
myList.add(new Float(1.0F));
if you wanted to add a float value to a list. The addition of boxing/unboxing in JDK1.4 tried to paper over this and have the compiler do this for us, but unfortunately you still have to understand the difference between the two to make sense of what's going on.

Related

Java8: double, float literals with suffix in lowercase and uppercase; type constructor and type boxing/unboxing

I see that floats and doubles have suffixes in different cases.
So what's the difference in suffix F and f for floats, D and d for doubles ?
Any history of this behavior ?
Also question about type constructor for example for float type (same behavior for double):
Why can I use "new Float(1L);" and cannot use "new Float("1L");" but "new Float(1.1F);" and "new Float("1.1F");" - works ok ?
And one more question about autoboxing/unboxing.
Why "float float23 = 1L"; works ok and "Float float12 = "1L";" - not ?
Thanks.
Code example:
package com.oca;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
#Getter
#Setter
#ToString
class Floats {
Float float11 = 1.1f;
Float float12 = 1.1F;
float float21 = 1.1f;
float float22 = 1.1F;
float float23 = 1L;
Float float31 = new Float(1.1F);
Float float32 = new Float(1.1f);
Float float33 = new Float(1L);
Float float41 = new Float("1.1F");
Float float42 = new Float("1.1f");
}
public class Main {
public static void main(String[] args) {
Floats floats = new Floats();
System.out.println(floats);
}
}
Output:
Floats(float11=1.1, float12=1.1, float21=1.1, float22=1.1, float23=1.0, float31=1.1, float32=1.1, float33=1.0, float41=1.1, float42=1.1)
Read the documentation. Float(String) leads to Float.valueOf(String), which finally leads to Double.valueOf(String), describing what is accepted and what is not, it provides both textual description and an actual regular expression.
This is how it ends, allowing f, F, d and D only:
"[fFdD]?))" +
"[\\x00-\\x20]*");// Optional trailing "whitespace"
It also points out relevant section (3.10.2) of the langspec which (the langspec itself) is a suggested reading anyway, if you are interested in the details of the language.
For the assignment part: you can store integer types into floating point ones, that is why it works. 1L is not a text to parse in runtime, but a text evaluated to a number in compilation time, which can be stored in a float with automatic conversion. The same applies to Float(1L) as it becomes a floating point value (probably a double, but I do not know for sure) even before invoking the constructor (Float has float, double and String constructors only).
Boxing-unboxing is a funny beast, it does no automatic conversion at all, and thus input has to be a float already. Practically you can choose between
Float f1=(float)1L;
Float f2=new Float(1L);
if you absolutely want to get a Float from 1L.
EDIT: if you know the answer, feel free not to ask.
If you open the Java 9 documentation of Float(String), it says
Deprecated. It is rarely appropriate to use this constructor. Use [...] valueOf(String) to convert a string to a Float object.
Which leads to
[...] To avoid calling this method on an invalid string and having a NumberFormatException be thrown, the documentation for Double.valueOf lists a regular expression which can be used to screen the input.
And link leads to exactly the same description in Java 9 docs, which I have linked for Java 7 (being Java 7 is visible both in the link, and on the page, and as I linked it from the internet, it does not really tell anything about what Java version "I am on"), containing exactly the same excerpt I have quoted here.
Ps: I have not written a word about the JDK source code, and neither have you in the original question. You asked about the why, not the how. In short: because it is specified this way.
Float constructors expects either float, double or string values (there are different 3 constructors). You're trying to pass a long which means that the long will be converted to float before the constructor will be called.
When you pass values as strings (to the constructor that expects a string) - it expects that you'll pass a float - not a long or anything else, that's why you'll get a NumberFormatException when you try calling: new Float("1L") for example.
Side-note: all these 3 constructors will generate deprecation warnings in Java 9, and state that you should use Float.valueOf() instead.

Safest way to initialize double variable in java

I used to initialize double variables with Double.NaN and fill them later depending on the input. If there were mistakes in inputs I just return Double.NaN. This practice backfired, when other part of application used my function as input and worked just OK, doing basic arithmetic and comparing NaNs with double (but didn't supposed to, I would expect exception).
The obvious solution would be to add Double.isNaN() at the end of my code and throw exception inside my function
But this is a highly used function in highly optimized code, so I'm unwilling to add extra check each time it is called. I would rather prefer break the whole application on wrong parameters once a year than add an extra check, esp. I heard that comparing to NaN takes longer than comparing to double. How do I achieve that and what are best practices in this situation?
EDIT
for example, I want to return first parameter for parametric function which I know nothing about depending on user input
private double getFirstFactor(HashMap <String, Double> userParams) {
double res = Double.NaN;
if(userParams.containsKey("factor1")) {
res = userParams.get("factor1");
}
return res;
}
Usage
double f1 = getFirstFactor(userParams);
double threshold = f(f1); // for example f1 * 100 + f1;
// ideally, code above breaks if f1 is not defined and I don't go futher
if(threshold >= 0) {
...
} else {
...
}
Don't do that.
NaN is used for the result of certain expressions (e.g. 0.0 / 0.0) and has the unique property that it compares false with itself.
You should always initialise double values with something sensible. Depending on your algorithm, 0.0 and 1.0 are often good values.
If you really can't do that then you could always use a Double, with null as your default-initialised value.
You should always validate your inputs before using them. If your inputs are invalid, you can throw an IllegalArgumentException before any computation is done at all. It makes it the caller's responsibility to use your code with correct inputs.
It's always better to fail fast, instead propagating invalid values throughout your system. This can cause big problems (as you probably have experienced).
Use boxed type Double and use null as default value insteed of Double.NaN. If I would need to stick to primitives, I would got for 0.0d as default value.

Java typecasting for retrieving integer part of a double as double

I sometimes tend to use (double)(long)(a*b/c) to store the integer part of the result as double. This works well for negative numbers too.
Is there any better way to achieve the same thing as I believe typecasting is a costly operation.
Please note I'm looking for Integer part of the number and not the rounded value.
For eg :
MyObj.setDouble((double)(long)(522.99))
MyObj.getDouble() returns 522.0 and not 523.0
Thanks.
Try Math.rint(double) or Math.round(double). Regardless of performance differences it's at least more clear and concise.
[Edit]
In response to your clarified question - "how do I get the integer part of a double without casting" (despite your title asking about rounding), try this:
public static double integerPart(double d) {
return (d <= 0) ? Math.ceil(d) : Math.floor(d);
}
integerPart(522.99); // => 522d
integerPart(-3.19); // => -3d
Of course, this form is likely no faster than casting since it's using a comparison and a method call.
Performance is not an issue here. But code (double)(long)(a*b/c) is ugly. You actually do not need casting at all if you assign the result to `double variable:
double d = a*b/c; exactly the same as double d = (double)(long)a*b/c;
You actually never need to perform casting when moving from lower to upper types. It is correct for primitives (e.g. int -> double) and for classes (e.g. ArrayList -> List).
What about Math.floor(double) I cant see the difference between integer part and rouding it down.

Determining input for Overloaded Method

I'm running into a bit of an issue with determining if the user input is an int or double.
Here's a sample:
public static int Square(int x)
{
return x*x;
}
public static double Square(double x)
{
return x*x;
}
I need to figure out how to determine based on the Scanner if the input is a int or double for the above methods. However since this is my first programming class, I'm not allowed to use anything that hasn't been taught - which in this case, has been the basics.
Is there anyway of possibly taking the input as a String and checking to see if there is a '.' involved and then storing that into an int or double?
Lastly, I'm not asking for you to program it out, but rather help me think of a way of getting a solution. Any help is appreciated :)
The Scanner has a bunch of methods like hasNextInt, hasNextDouble, etc. which tell you whether the "next token read by the Scanner can be interpreted as a (whatever)".
Since you mentioned you've learned about the Scanner object, I assume the methods of that class are available to you for your use. In this case, you can detect if an input is an integer, double, or just obtain an entire line. The methods you would most be interested here would be the hasNextDouble() method (returns a boolean indicating whether or not the current token in the Scanner is actually a double or not) and the nextDouble() method (if the next token in the Scanner is in fact a double, parse it from the Scanner as one). This is probably the best direction for determining input types from a file or standard input.
Another option is to use the wrapper classes static methods for converting values. These are generally named like Integer.parseInt(str) or Double.parseDouble(str) which will convert a given String object into the appropriate basic type. See the Double classes method pasrseDouble(String s) for more details. It could be used in this way:
String value = "123.45"
double convertedValue = 0.0;
try {
convertedValue = Double.parseDouble(value);
} catch (NuberFormatException nfe) {
System.err.println("Not a double");
}
This method is probably best used for values that exist within the application already and need to be verified (it would be overkill to construct a Scanner on one small String for this purpose).
Finally, yet another potential (but not very clean, straightforward, or probably correct technique) could be looking at the String object directly and trying to find if it contains a decimal point, or other indicators that it is in fact a double. You may be able to use indexOf(String substr) to determine if it appears in the String ever. I suspect this method has a lot of potential problems though (say for example, what if the String has multiple '.' characters?). I wouldn't suggest this route because it is error prone and hard to follow. It might be an option if that's what the constraints are, however.
So, IMHO, your options should go as follow:
Use the Scanner methods hasNextDouble() and nextDouble()
Use the wrapper class methods Double.parseDouble(String s)
Use String methods to try and identify the value (avoid this technique at all costs if either of the above options are available).
Since you think you won't be allowed to use the Scanner methods there are a number of alternatives you try. You mentioned checking to see if a String contains a .. To do this you could use the contains method on String.
"Some words".contains("or") // evaluates to true
The problem with this approach is that there are many Strings that contain . but aren't floating point numbers. For examples, sentences, URLs and IP addresses. However, I doubt you're lecturer is trying to catch you out with and will probably just be giving you ints and doubles.
So instead you could try casting. Casting a double to an int results in the decimal portion of the number being discarded.
double doubleValue = 2.7;
int castedDoubleValue = (int) doubleValue; // evaluates to 2
double integerValue = 3.0;
int castedIntegerValue = (int) integerValue; // evaluates to 3
Hopefully, that should be enough to get you started on writing a solution to the problem.
Can be checked like this
if(scanner.hasNextDouble()}
{
System.out.println("Is double");
}
if(scanner.hasNextDouble()}
{
System.out.println("Is double");
}

How to convert array of floats to array of doubles in Java?

I have an array of floats and I would like to convert it to an array of doubles in Java. I am aware of the obvious way of iterating over the array and creating a new one. I expected Java to digest a float[] smoothly where it wishes to work with double[]... but it can not work with this.
What is the elegant, effective way of doing this conversion?
Basically something has to do the conversion of each value. There isn't an implicit conversion between the two array types because the code used to handle them after JITting would be different - they have a different element size, and the float would need a conversion whereas the double wouldn't. Compare this to array covariance for reference types, where no conversions are required when reading the data (the bit pattern is the same for a String reference as an Object reference, for example) and the element size is the same for all reference types.
In short, something will have to perform conversions in a loop. I don't know of any built-in methods to do this. I'm sure they exist in third party libraries somewhere, but unless you happen to be using one of those libraries already, I'd just write your own method. For the sake of convenience, here's a sample implementation:
public static double[] convertFloatsToDoubles(float[] input)
{
if (input == null)
{
return null; // Or throw an exception - your choice
}
double[] output = new double[input.length];
for (int i = 0; i < input.length; i++)
{
output[i] = input[i];
}
return output;
}
In Java 8 you can, if you really want to, do:
IntStream.range(0, floatArray.length).mapToDouble(i -> floatArray[i]).toArray();
But it's better (cleaner, faster, better semantics) to use Jon Skeet's function.
Do you actually need to copy your float array to a double array? If you are having trouble with the compiler and types when using the floats you can use this...
float x = 0;
double d = Double.valueOf(x);
What advantage do you get by taking a copy? If you need greater precision in the results of computations based on the floats then make the results double. I can see quite a lot of downsides to having a copy of the array, and performing the copy function, especially if it is large. Make sure you really need to do it.
HTH

Categories

Resources