What is the "meta" for declaring binary numbers in Java? - java

I'm just wondering why everyone declares binary numbers like this:
int val1 = 0b1010;
int val2 = 0b10000001;
when this declaring a number like this float val1 = 0b1010; works as well.
I'm working on a project that deals with image pixel color values, so I need to manipulate the saturation level of each color value (by reading them off the image) into a float between 0.0 and 1.0. I'm assuming declaring each initial binary as an integer has something to do with ease of manipulation when masking and such, but I haven't seen any particular rule of thumb other than every example that I've seen initializing the variables as an int.
(For my use an example would be:
double val = 0b100000; //this is equivalent to 32.0
System.out.println(test1/255.0); //this gives out the ratio, namely 0.12549...
In this case I would skip the need to cast anything...)
Thank you for taking the time to clear this up.

When you declare float val1 = 0b1010;, that is the equivalent of declaring float val1 = (float)0b1010; The cast from int to float is implicit, but it is still performed.

Related

Java int cast to float cast to int does not equal original int

Using this snippet:
public static void main(String[] args){
int i = XXX;
System.out.println( (int) ( (float) i ) );
}
If int i = 1234; then the output is 1234
If int i = Integer.MAX_VALUE; then the output is equal to Integer.MAX_VALUE
However, if int i = 1234567990;, then the output is 1234567936, which is not equal to i.
And if int i = 1235567990;, then the output is 1235568000, which is also not equal to i.
How does this casting conversion math work?
This is entirely normal for floating point maths. Both int and float are 32-bit values. float only has about 7 significant digits of precision, because it uses some of the bits for scale. As you get to large values, "adjacent" float values (i.e. going from one precisely-representable value to the next one up) are more than 1 apart - so any integer between those two adjacent values can't be represented precisely as a float.
Another way of looking at this is a version of the pigeonhole principle:
Both float and int have 2^32 possible bit patterns
There's a valid mapping from every int to a float value
Every bit pattern is a valid int, so there are 2^32 possible integer values
float also contains the value 1.5 (and many other non-integers, but we only need one of them to prove the point)
Therefore at least two int values must map to the same float, which means the mapping cannot be reversible in every case
Note that if you use double, you're fine - every int can be cast to double and then cast back to int, and you'll get the original value. However, using double and long (instead of int) you get the same problem, for the same reason, but using 64 bits instead of 32.
How does this casting conversion math work?
Casting an int to a float works the same way any float operation works: Do the math (which in this case is nothing - just take the int as is), then convert it to the 'nearest representable float' - that float which is closer to the result of the calculation than any other.
Why is it 'lossy'? See the other answer.
What's the math behind which floats are representable? Wikipedia's page on IEEE754 floating point representation explains that.

Float to Int vs Int to Float automatic conversion

I'm studying java by Herbert Schildt's "Java for beginners" book. It is said that, being a destiny variable compatible and sufficiently big to store an origin one, an automatic conversion is done.
That being said, an Int should be able to store an Float and vice-versa, since they both have a 4 bytes size.
public class MyClass {
public static void main(String args[]) {
int i = 10;
float f = i;
float ff = 10;
int ii = ff;
}
}
However, when compiled, this piece of code generetes the following error:
/MyClass.java:15: error: incompatible types: possible lossy conversion from float to int
int ii = ff;
^
1 error
Why is there that, being a compatible type and sufficiently big to store each other, a float can store an int but an int cannot store a float?
Because float contains numbers also after the decimal point and int does not. Without this you shouldn't be able to simply trim the decimal part from the number by explicitly casting the float to int too.
an Int should be able to store an Float and vice-versa, since they both have a 4 bytes size.
The size of the data is not the important part. Rather it is about the values which can be stored in the give number of bytes. int can only store whole number values between -2^31 and 2^31-1. On the other hand, float can store decimal values.
As you can see, you can store a int into a float, but you can't put a float inside a int.
This heappens because the internal structure of float is a decimal number and int, as its name says, is integer.
For more information you can take a look into this discussion about How are floating point numbers are stored in memory.
Int to float is never a lossy conversion if the integer value will be within the range of maximum integer value that float can store as value will always be stored/converted to <intvalue>.0 like 4 will be stored as 4.0. But in case of conversion from float to int, your fraction value will be lost so JVM gives you such error. If you can take such risk then you have to explicitly convert the float value into int.

Convert Array to Floats Array with notation Java

Sorry for the title name but this is probably a funny question. i need to have this like it is. I have an array of floats in the format [10.0, 20.0, 30.0, 40.0, 50.0] i need the array to be represented like [10.0f, 20.0f, 30.0f, 40.0f, 50.0f]. I have tried using array List to convert and add the notation and convert back.. but no matter what i try, i still get a float array that looks like a double. Any ideas Please?
even tried something like this:
ArrayList<String> valuelist = new ArrayList<String>();
for(int z = 0; z < mValues.length; z++){
valuelist.add(Float.toString(mValues[z]) + "f");
} //its fine here but later changes
Object[] objarray2 = valuelist.toArray();
String[] stringfloat = Arrays.copyOf(objarray2, objarray2.length, String[].class);
float[] myfloat = new float[stringfloat.length];
for(int j =0; j< myfloat.length; j++){
//myfloat[j] = Float.parseFloat(stringfloat[j]);
myfloat[j] = Float.valueOf(stringfloat[j]);
}
f is used to tell the compiler that treat this as float number. If you want your array in this format use an array of string and append f in each element
As per JLS:
A floating-point literal is of type float if it is suffixed with an ASCII letter F or f; otherwise its type is double and it can optionally be suffixed with an ASCII letter D or d (ยง4.2.3).
You have:
myfloat[j] = Float.valueOf(stringfloat[j]);
Here's Float.valueOf(String):
public static Float valueOf(String s) throws NumberFormatException
{
return new Float(FloatingDecimal.readJavaFormatString(s).floatValue())
}
As you can see, it returns a Float, which is created through Float(float) constructor, which is simply:
public Float(double value)
{
this.value = (float) value;
}
The readJavaFormatString(String) converts the String to a double, and .floatValue() converts the double, wrapped in a FloatingDecimal to a float, which is passed to the above constructor.
So, im short, you do have a float.
NB:
float num1 = XYZ;
float num2 = XYZf;
Despite the different notation, num1 and num2 compile to the same bytecode (where XYZ are some numbers, say 123); however, you cannot make an assignment of a number ending in an f to say an int. Additionally, if you try to put an int into a float, you do not need the f at the end, but if your number has any numbers to the right of the radix, you need to append the f so that it will compile with a possible loss of precision error.
Also, you really shouldn't be using float unless there's a good reason to do so, especially if you're planning to use == for comparison; instead, use double. float and double are essentially the same thing, except that double is 64-bits, whereas a float is 32-bits, so a double is more precise.
Keep the original array where members are float and just create a "String myToString()" method to print it like you want, with the +"f".
I mean, create a personalized method to print the array like you want it to appear.
I assume you just want the print out of the array of float to "appear" with a final f.
The representation in the machine of the number will not change with an f at the end or not.
The final f in the string is useful when parsing a number, so you the parser knows which kind of number it is, if you already do not tell it.

Java math logic error

I have the following code in my project:
int percent = 2;
int count = 10;
int percentagefill = (percent/10)*count;
System.out.println(percentagefill);
Basically what is happening is that, I'm setting two variables, percent and count. I then calculate the percentage fill. For some strange reason the percentage fill is resulting in a 0, when in this case it should be 2. Any ideas why? Thanks in advance.
intdivided by int will still result in int. In this case:
(percent/10)*count
= (2/10)*10
= (0) * 10 <-- 0.2 is rounded down to 0
= 0
You can read this question for reference. Also, here's the Java spec where is says that integer division is rounded towards 0. As for the fix, as long as floating point precision does not become an issue, just use double as PaulP.R.O said.
You could divide by 10.0, or change int percent to double percent in order to force a conversion to double. Otherwise, you are getting integer division, which truncates off the decimal part.
Here is a relevant question: "Java Integer Division, How do you produce a double?"
if you really need the result to be an int, you could do the multiply before the divide to avoid the integer division giving you zero.
int percentagefill = (percent*count)/10;
Change this line:
int percentagefill = (percent/10)*count;
To:
double percentagefill = (percent/10.0)*count;
This will use floating point arithmetic (because of the 10.0 instead of 10), and store the result in a double (which has precision past the decimal point unlike an int).
As others have mentioned, you're losing precision with integer division
The solution depends on your needs: if your result needs to be an integer anyway, multiply first:
int percentagefill = (percent*count)/10;
Could be "good enough" for you (you'll get the correct answer rounded down).
If you need to be able to get fractional answers, you need to convert things to floating point types:
double percentagefill = (percent/10.0)*count;
// ^ the .0 makes this a double,
// forcing the division to be a
// floating-point operation.
It's easy to fix:
int percent = 2;
int count = 10;
double percentagefill = (percent/10.0)*count;
System.out.println(percentagefill);
Dave Newton, your answer should have been an answer. :)
The integer 2 / the integer 10 = 0.
The integer 0 * the integer 10 = 0.
You will need a float or double data type. While working with information, always be weary of chances for the interpreter to make data type assumptions and "casts". println takes an intefer and casts to a string for display is one example.
Most of my work is in php and when working with values, 0, NULL, ERROR can all be different things and can yield unexpected results. Sometimes you may need to explicitly cast a variable to a different data type to get the intended results.
This is so due to the fact that you are using the integer data type when you should be using a floating-point data type such as double. This code should result in 2.0:
double percent = 2;
double count = 10;
double percentagefill = (percent/10)*count;
System.out.println(percentagefill);

Converting double to integer in Java

In Java, I want to convert a double to an integer, I know if you do this:
double x = 1.5;
int y = (int)x;
you get y=1. If you do this:
int y = (int)Math.round(x);
You'll likely get 2. However, I am wondering: since double representations of integers sometimes look like 1.9999999998 or something, is there a possibility that casting a double created via Math.round() will still result in a truncated down number, rather than the rounded number we are looking for (i.e.: 1 instead of 2 in the code as represented) ?
(and yes, I do mean it as such: Is there any value for x, where y will show a result that is a truncated rather than a rounded representation of x?)
If so: Is there a better way to make a double into a rounded int without running the risk of truncation?
Figured something: Math.round(x) returns a long, not a double. Hence: it is impossible for Math.round() to return a number looking like 3.9999998. Therefore, int(Math.round()) will never need to truncate anything and will always work.
is there a possibility that casting a double created via Math.round() will still result in a truncated down number
No, round() will always round your double to the correct value, and then, it will be cast to an long which will truncate any decimal places. But after rounding, there will not be any fractional parts remaining.
Here are the docs from Math.round(double):
Returns the closest long to the argument. The result is rounded to an integer by adding 1/2, taking the floor of the result, and casting the result to type long. In other words, the result is equal to the value of the expression:
(long)Math.floor(a + 0.5d)
For the datatype Double to int, you can use the following:
Double double = 5.00;
int integer = double.intValue();
Double perValue = 96.57;
int roundVal= (int) Math.round(perValue);
Solved my purpose.

Categories

Resources