strange behaviour of the java - java

hello I have some question about java, why the following code return strange value?
System.out.println("Strange " + (20 * 232792560)/20);
why do I recieve 18044195?

Because (20 * 232792560) overflows the range of an int, and wraps round the number range several times to become 360883904. That is then divided by 20 to give you the result that you see.
If you want the correct result, then you need to do:
System.out.println("Strange " + (20 * 232792560L) / 20);
(Marking a literal with an L means that the constant maths will be done with long, rather than with int, so this will no longer overflow.)

Because (20 * 232792560) will perform integer based multiplication and the result is obviously out of int's range, hence the value will be truncated.

Because 20 * 232792560 does not fit in 4 bytes (integer value).
So you got:
20 * 232792560 = 360883904; // because of int overflow
360883904 / 20 = 18044195;

Related

Why is my implementation of math.random in my class only returning 0? [duplicate]

This question already has answers here:
math.random, only generating a 0?
(4 answers)
Closed 2 years ago.
I've been trying to create a class to roll dice for games, and my code for one aspect of it is:
public int[] yahtzeeRoll() {
int[] rolls1 = new int[6];
for (int i = 0; i < 6; i++) {
rolls1[i] = ((int) Math.random()*6+1);
}
return rolls1;
}
yet, when I call it in the main method, it only returns 1 for each of the values. Why is this? How can I fix my code so that it generates 6 different numbers when I print the array in the main method?
You are casting the double value returned by Math.random() to int before multiplying by 6, and since Math.random() returns a value < 1, casting it to int results in 0.
Change
rolls1[i] = ((int) Math.random()*6+1);
to
rolls1[i] = (int)(Math.random()*6)+1;
The type casting by appending (type) takes precedence over the * 6 bits afterwards. Therefore, the result from Math.random() is always casted into 0 before you multiply it by 6, which turns out to always be 0 as well.
This answer points to this site which explains it quite well.
Either (int) (Math.random() * 6) + 1 or (int) (Math.random() * 6 + 1) would work as you have intended.
Math.random returns a floating point number between 0 and 1 but you are truncating it down to 0 by using (int) type cast before it. Use parentheses around your expression and then prepend (int) to that if you do wish to use integer truncation.
Btw, I think same sequence should be generated at each run if you don't seed the pseudo-random engine, say with current time or something.
Let's look at the expression.
((int) Math.random()*6+1)
Now Math.random() returns a double that is >=0 and <1.
You then cast that result to an int which means it will always become 0.
If you use.
(int)(Math.random()*6+1)
You are taking the double between 0 and 1, multiplying it by 6 (giving 0 ... 6) adding 1 and then casting to an int. This looks more like what you are looking for.
Math.random() returns double value in range [0, 1) (greater than or equal to 0.0 and less than 1.0). Then you cast that double value to int, so it always results in 0. After that you add 1 to it, so the result always remains 1.
You should cast result of multiplication - Math.random() * 6 instead of casting Math.random() return value:
rolls1[i] = (int)(Math.random()*6)+1;
By the way, you should be aware of operators precedence in Java language. You can have a look here: operator precedence to see nice table that shows that casting has a higher priority than multiplication and addition - this is the reason, why (Math.random()*6) is put in parenthesis for casting (this way you avoid casting only Math.random())
PS. There is also a link to table of operator precedence in official Java tutorial, but it doesn't exactly fit to your problem as it doesn't contain operation of casting - this is the reason, why I provided another link firstly.
You can take a clue from the below output presentation which is self explanatory.
Code:
double random = Math.random();
System.out.println("Math.random()>>"+random);
System.out.println("Math.random()*6>>"+random*6);
System.out.println("(int)(Math.random()*6)>>"+(int)(random*6));
System.out.println("Math.random()*6+1>>"+random*6+1); //+1 here is treated as a string by java and will add at the end of the number
System.out.println("(Math.random()*6+1)>>"+(random*6+1)); //number random*6 will be incremented by 1 as enclosing () will treat them as numbers
System.out.println("(int)(Math.random()*6+1)>>"+(int)(random*6+1));
Output:
Math.random()>>0.6793602796545469
Math.random()*6>>4.076161677927281
(int)(Math.random()*6)>>4
Math.random()*6+1>>4.0761616779272811
(Math.random()*6+1)>>5.076161677927281
(int)(Math.random()*6+1)>>5

How to print long primitive in Java [duplicate]

This question already has answers here:
Multiplication operation in Java is resulting in negative value
(4 answers)
Closed 6 years ago.
Relatively new to Java and possibly some stupid question. Here is the code:
long a = 3232235521L;
long b = 192 * 16777216 + 168 * 65536 + 0 * 256 + 1;
System.out.println("a="+a);
System.out.println("b="+b);
The output:
a=3232235521
b=-1062731775
According to Java documentation max value for long 2^63-1 and that is: 9223372036854775807. So for b, there is no overflow, so why b isn't 3232235521?
In line 2 of your code, all your operands are integers, which is why the results of the operations will also be an integer.
Since the result(3,232,235,521) will not fit inside an integer(max value being 2^31 - 1), this results in an integer overflow, which is why you are getting the negative result.
So, you will need to use Long literals to get an accurate result. Change Line 2 to the below code.
long b = 192L * 16777216L + 168L * 65536L + 0L * 256L + 1L;
The above code should give you the correct output.
You are using integer primitives during the math and it's only converted at the end, after the integer overflow. You might want to use 192L * 16777216L + 168L * 65536L + 0L * 256L + 1L;
You are only doing the conversion to long on the assignment - up until that point everything is an integer and that is why you are seeing an overflow halfway through your calculation.
The code should be:
long b = 192l * 16777216l + 168l * 65536l + 0l * 256l + 1l;

Rounding to tens in Java formula doesn't make sense

I found this formula on SO but I don't get how it works:
(n + 5) / 10 * 10
This rounds a number to the multiple of ten but when I calculate it it just divides and multiplies back to n+5. How does this actually work?
Example (in Java):
(24 + 5) / 10 * 10 = 20
While it should actually be 29 as far as I know.
You're doing these operations on int. That's why, every operation result is also an int. What happens is:
(24 + 5) = 29
29 / 10 = 2 (because the fraction part is always dropped in ints)
2 * 10 = 20
This rounding method works fine only for float and double. You can try to cast the int to double.

How to convert large integer number to binary?

Sorry for a possible duplicate post, I saw many similar topics here but none was exactly I needed. Before actually posting a question I want to explicitly state that this question is NOT A HOMEWORK.
So the question is: how to convert a large integer number into binary representation? The integer number is large enough to fit in primitive type (Java long cannot be used). An input might be represented as a string format or as an array of digits. Disclaimer, This is not going to be a solution of production level, so I don't want to use BigInteger class. Instead, I want to implement an algorithm.
So far I ended up with the following approach:
Input and output values represented as strings. If the last digit of input is even, I prepend the output with "0", otherwise - with "1". After that, I replace input with input divided by 2. I use another method - divideByTwo for an arithmetical division. This process runs in a loop until input becomes "0" or "1". Finally, I prepend input to the output. Here's the code:
Helper Method
/**
* #param s input integer value in string representation
* #return the input divided by 2 in string representation
**/
static String divideByTwo(String s)
{
String result = "";
int dividend = 0;
int quotent = 0;
boolean dividendIsZero = false;
while (s.length() > 0)
{
int i = 1;
dividend = Character.getNumericValue(s.charAt(0));
while (dividend < 2 && i < s.length())
{
if (dividendIsZero) {result += "0";}
dividend = Integer.parseInt(s.substring(0, ++i));
}
quotent = dividend / 2;
dividend -= quotent * 2;
dividendIsZero = (dividend == 0);
result += Integer.toString(quotent);
s = s.substring(i);
if (!dividendIsZero && s.length() != 0)
{
s = Integer.toString(dividend) + s;
}
}
return result;
}
Main Method
/**
* #param s the integer in string representation
* #return the binary integer in string representation
**/
static String integerToBinary(String s)
{
if (!s.matches("[0-9]+"))
{
throw new IllegalArgumentException(s + " cannot be converted to integer");
}
String result = "";
while (!s.equals("0") && !s.equals("1"))
{
int lastDigit = Character.getNumericValue(s.charAt(s.length()-1));
result = lastDigit % 2 + result; //if last digit is even prepend 0, otherwise 1
s = divideByTwo(s);
}
return (s + result).replaceAll("^0*", "");
}
As you can see, the runtime is O(n^2). O(n) for integerToBinary method and O(n) for divideByTwo that runs inside the loop. Is there a way to achieve a better runtime? Thanks in advance!
Try this:
new BigDecimal("12345678901234567890123456789012345678901234567890").toString(2);
Edit:
For making a big-number class, you may want to have a look at my post about this a week ago. Ah, the question was by you, never mind.
The conversion between different number systems in principle is a repeated "division, remainder, multiply, add" operation. Let's look at an example:
We want to convert 123 from decimal to a base 3 number. What do we do?
Take the remainder modulo 3 - prepend this digit to the result.
Divide by 3.
If the number is bigger than 0, continue with this number at step 1
So it looks like this:
123 % 3 == 0. ==> The last digit is 0.
123 / 3 == 41.
41 % 3 == 2 ==> The second last digit is 2.
41 / 3 == 13
13 % 3 == 1 ==> The third digit is 1.
13 / 3 == 4
4 % 3 == 1 ==> The fourth digit is 1 again.
4 / 3 == 1
1 % 3 == 1 ==> The fifth digit is 1.
So, we have 11120 as the result.
The problem is that for this you need to have already some kind of division by 3 in decimal format, which is usually not the case if you don't implement your number in a decimal-based format (like I did in the answer to your last question linked above).
But it works for converting from your internal number format to any external format.
So, let's look at how we would do the inverse calculation, from 11120 (base 3) to its decimal equivalent. (Base 3 is here the placeholder for an arbitrary radix, Base 10 the placeholder for your internal radix.) In principle, this number can be written as this:
1 * 3^4 + 1 * 3^3 + 1*3^2 + 2*3^1 + 0*3^0
A better way (faster to calculate) is this:
((((1 * 3) + 1 )*3 + 1 )*3 + 2)*3 + 0
1
3
4
12
13
39
41
123
123
(This is known as Horner scheme, normally used for calculating values of polynomials.)
You can implement this in the number scheme you are implementing, if you know how to represent the input radix (and the digits) in your target system.
(I just added such a calculation to my DecimalBigInt class, but you may want to do the calculations directly in your internal data structure instead of creating a new object (or even two) of your BigNumber class for every decimal digit to be input.)
Among the simple methods there are two possible approaches (all numbers that appear here decimal)
work in decimal and divide by 2 in each step as you outlined in the question
work in binary and multiply by 10 in each step for example 123 = ((1 * 10) + 2) * 10 + 3
If you are working on a binary computer the approach 2 may be easier.
See for example this post for a more in-depth discussion of the topic.
In wikipedia, it is said:
For very large numbers, these simple methods are inefficient because
they perform a large number of multiplications or divisions where one
operand is very large. A simple divide-and-conquer algorithm is more
effective asymptotically: given a binary number, it is divided by
10^k, where k is chosen so that the quotient roughly equals the
remainder; then each of these pieces is converted to decimal and the
two are concatenated. Given a decimal number, it can be split into two
pieces of about the same size, each of which is converted to binary,
whereupon the first converted piece is multiplied by 10^k and added to
the second converted piece, where k is the number of decimal digits in
the second, least-significant piece before conversion.
I have tried, this method is faster than conventional one for numbers larger than 10,000 digits.

why long COOKIE_TIMEOUT = 1000 * 60 * 60 * 24 * 30 return negative? [duplicate]

This question already has answers here:
Multiplication operation in Java is resulting in negative value
(4 answers)
Closed 8 years ago.
final long COOKIE_TIMEOUT = 1000 * 60 * 60 * 24 * 30;
Output: -1702967296
Someone told me to put L after 1000 & it works
final long COOKIE_TIMEOUT = 1000L * 60 * 60 * 24 * 30;
Output: 2592000000
Why does that happen?
Integer overflow, put 1000L, this will force long conversion
UPDATE
Slightly longer explanation:
If you just do 1000*10 for example, java will see them as integers.
In your original code, you were doing an integer calculation which overflowed, then cast the overflowed value to long.
However if you put L after the first number, java will see them as longs (left-most operand defines the granularity) and you won't get an overflow.
As another example take this code:
double a = 5 / 2;
double b = 5d / 2;
System.out.println(a + " != " + b);
This will print out:
2.0 != 2.5
Why? When calculating a, java sees 5 and 2 as integers and does an integer division, then casts the result to a double. When calculating b you tell java that 5 is actually a double at which point it performs a double division.
Although COOKIE_TIMEOUT is long the right-hand expression consists of integers, so its type is int. The result is greater than Integer.MAX_VALUE that causes overflow. When at least one operand in your expression belongs to higher type (e.g. long) whole expression becomes long and overflow does not happen.
This is what you did in your second example when you added L modifier after one of the numeric constants. This constant became long, so the expression became long too.
This behavior is due to the type of the expression selected by the Java compiler. In this case it looks something like so:
int * int -> int (which overflows here during the multiplication)
long * long -> long
long * int = long * long (by promotion) -> long
int * long = long (by promotion) * long -> long
This promotion happens pretty much universally for the math operators: the widest/largest type is used, with the smaller type being promoted and the x op x -> x expression being applied (classically, integer vs. floating division).
The L results in a long value and thus the multiplication selected is long * long (by promotion) -> long, which is free from the immediate overflow discovered. The long expression result type propagates to all the other multiplications.
Bonus points: it would still fail (overflow) if written as 1000 * 60 * 60 * 24 * 30 * 1L, why?
It is greatter than Integer.MAX_VALUE which is 2147483647
By default all numeric litaral are considered as Integer. to define a Long numeric value you have to add L or 'l' with the number.
The reason of that behavior is integer overflow.
Your first statement can be understand like this:
long time = 1000 * 60 * 60 * 24 * 30;
is the same as
int time = 1000 * 60 * 60 * 24 * 30;
long timel = time;
First you compute the expression, then you assign to long type;
When you put suffix L to literal you define it as long type.
JSL 3.10.1. Integer Literals
An integer literal is of type long if it is suffixed with an ASCII
letter L or l (ell); otherwise it is of type int (§4.2.1).
long time = 1000L * ( 60 * 60 * 24 * 30);
can be written also as
long time = ((long) 1000) * ( 60 * 60 * 24 * 30);
More about Primitive Data Types
It is causing for Integer overflow(Max value upto 2147483647).
You can postfix L at the end of the any numeric value.
Like 1000L
Then it forcely converts into Long type
What happens here is that the right hand side is evaluated before the assignment to the left hand side. Since you are multiplying several ints, the resulting type will be int. Then, after evaluating the right hand side, it will see that it is supposed to assign this value to a long, and do the casting automatically.
So you have:
Evaluated right hand side as int: 1000 * 60 * 60 * 24 * 30 = 2,592,000,000.
The maximum value of an int is: 2,147,483,647.
So you have an overflow, which makes the int negative. This is then assigned to a long, still negative.
When you specify one of the operands on the right hand side to be long, then the expression will be evaluated has a long, which has a much larger maximum value.
Every number in the formula is an Integer, hence Java will perform all calculations in Integer and store the result temporarily as Integer. However the result exceeds Integer Max range (overflow), so it becomes negative.
1000 * 60 * 60 * 24 * 30 = 2592000000 (exceeds Integer.MAX_VALUE)
Only when Java needs to assign it to the Long variable Java will cast it into a Long. Since the result is already wrong result (due to overflow) then the Long variable will be assigned with the wrong result.
However if you already declare the 1000 as Long (1000L), then the remaining calculations will be done as Long instead of Integer.

Categories

Resources