I have a problem that requires me to go well beyond the Max Value of Integers in Java. How can I have an exception so that Java will let me do this, or get around these rules of Java?
Use a long value or Long wrapper.
When you've reached Long.MAX_VALUE then use BigInteger, which has a very large capacity, at least from -2^Integer.MAX_VALUE to 2^Integer.MAX_VALUE.
Come back for additional tips when BigInteger is no longer enough.
Related
public class ConstantsAndCasting{
public static void main (String args[]){
long hugeNum = 23456013477456L;
int smallNum = (int)hugeNum;
System.out.println(hugeNum);
System.out.println(smallNum);
}
}
The output to the code listed above is:
23456013477456
1197074000
It appears as though when casting a long to an integer value, java retains 32 bits starting from the right working left. What results is a value that is closer to 0 than to the original long value. This totally makes sense from a machine perspective but what is the practical use for this? It seems like you'd be better off using the random number generator to produce 10 random characters.
Thanks in advance!
It's a little unclear how to answer that... As with any type conversion, it iis used when you have a value of one type (in this case, long) but you need a value of a different type (in this case, int).
Yes, sometimes it will give you unwanted results, because of the limitations of the casting operation (Which, in turn, are based on the limitations of the data types). But picking one of those out, and saying "so what's the point in ever doing this operation", would be like saying "if I have two ints, a and b, each valued at 2,000,000,000 - adding them doesn't get the desired result... so what's the point adding ints?"
The primary useful purpose of casting a long to an int is to take a long value which is in the range -2147483648..2147483647 and use that number with code that expects an int value in that range. The behavior with values was outside that range was chosen because:
The designers of Java wanted to fully specify its behavior whenever practical.
Taking the bottom 32 bits and ignoring the top 32 bits was faster than any other consistent course of action which would work sensibly with values in the range -2147483648..2147483647.
There are a number of situations where other courses of action might sometimes allow more efficient code generation if consistency wasn't required, or more useful semantics if speed wasn't required. The approach that was taken, however, offers the best compromise between speed, usefulness, and consistency.
I'm new here so please excuse my noob mistakes. I'm currently working on a little project of mine that sees me dealing with digits with a length in the forty thousands and beyond.
I'm currently using BigInteger to handle these values, and I need something that performs faster. I've read that BigInteger uses an array of integers in its implementation, and what I need to know is whether BigInteger is using each index in this array to represent each decimal point, as in 1 - 9, or is it using something more efficient.
I ask this because I already have an implementation in mind that uses bit operations, which makes it more efficient, memory and processing wise.
So the final question is - is BigInteger already efficient enough, and should I just rely on that? It would better to know this rather than putting it to the test unnecessarily, which would take a lot of time.
Thank you.
At least with Oracle's Java 8 and OpenJDK 8, it doesn't store one decimal digit per int. It stores full 32-bit portions per 32-bit int in the int[], which can be seen with its source code.
Bit operations are fast for it, since it's a sign-magnitude value and the magnitude is stored packed just as you'd expect, just make sure that you use the relevant BigInteger bitwise methods rather than implementing your own.
If you still need more speed, try something like GMP, though be aware that it uses a LGPL or GPL license. It would also be better to use it outside of Java.
My question is related to this
How can I check if multiplying two numbers in Java will cause an overflow?
In my application, x and y are calculated on the fly and somewhere in my formula I have to multiply x and y.
int x=64371;
int y=64635;
System.out.println((x*y));
I get wrong output as -134347711
I can quickly fix above by the changing variable x and y from type int to long and get correct answer for above case. But, there is no gurantee that x and y won't grow beyond max capacity of long as well.
Question
Why does I get a negative number here, even though I am not storing the final result in any variable? (for curiosity sake)
Since, I won't know the value of x and y in advance, is there any quicker way to avoid this overflow. Maybe by dividing all x and y by a certain large constant for entire run of the application or should I take log of x and y before multiplying them? (actual question)
EDIT:
Clarification
The application runs on a big data set, which takes hours to complete. It would be nicer to have a solution which is not too slow.
Since the final result is used for comparison (they just need to be somewhat proportional to the original result) and it is acceptable to have +-5% error in the final value if that gives huge performance gain.
If you know that the numbers are likely to be large, use BigInteger instead. This is guaranteed not to overflow, and then you can either check whether the result is too large to fit into an int or long, or you can just use the BigInteger value directly.
BigInteger is an arbitrary-precision class, so it's going to be slower than using a direct primitive value (which can probably be stored in a processor register), so figure out whether you're realistically going to be overflowing a long (an int times an int will always fit in a long), and choose BigInteger if your domain really requires it.
You get a negative number because of an integer overflow: using two-s complement representation, Java interprets any integer with the most significant bit set to 1 as a negative.
There are very clever methods involving bit manipulation for detecting situations when an addition or subtraction would result in an overflow or an underflow. If you do not know how big your results are going to be, it is best to switch to BigInteger. Your code would look very different, though, because Java lacks operator overloading facilities that would make mathematical operations on BigInteger objects look familiar. The code will be somewhat slower, too. However, you will be guaranteed against overflows and underflows.
EDIT :
it is acceptable to have +-5% error in the final value if that gives huge performance gain.
+-5% error is a huge allowance for error! If this is indeed acceptable in your system, than using double or even float could work. These types are imprecise, but their range is enormously larger than that of an int, and they do not overflow so easily. You have to be extremely careful, though, because floating-point data types are inherently inexact. You need to always keep in mind the way the data is represented to avoid common precision problems.
Why does I get a negative number here, even though I am not storing
the final result in any variable? (for curiosity sake)
x and y are int types. When you multiply them, they are put into a piece of memory temporarily. The type of that is determined by the types of the originals. int*int will always yield an int. Even if it overflows. if you cast one of them to a long, then it will create a long for the multiplication, and you will not get an overflow.
Since, I won't know the value of x and y, is there any quicker way to
avoid this overflow. Maybe by dividing all x and y by a certain large
constant for entire run of the application or should I take log of x
and y before multiplying them? (actual question)
If x and y are positive then you can check
if(x*y<0)
{
//overflow
}
else
{
//do something with x*y
}
Unfortunately this is not fool-proof. You may overrun right into positive numbers again. for example: System.out.println(Integer.MAX_VALUE * 3); will output: 2147483645.
However, this technique will always work for adding 2 integers.
As others have said, BigInteger is sure not to overflow.
Negative value is just (64371 * 64635) - 2^32. Java not performs widening primitive conversion at run time.
Multiplication of ints always result in an int, even if it's not stored in a variable. Your product is 4160619585, which requires unsigned 32-bit (which Java does not have), or a larger word size (or BigInteger, as someone seem to have mentioned already).
You could add logs instead, but the moment you try to exp the result, you would get a number that won't round correctly into a signed 32-bit.
Since both multiplicands are int, doing the multiplication using long via casting would avoid an overflow in your specific case:
System.out.println(x * (long) y);
You don't want to use logarithms because transcendental functions are slow and floating point arithmetic is imprecise - the result is likely to not be equal to the correct integer answer.
In my android application(Audio Processing) i use a long type variable to calculate the position where it is being paused, but the application gave me strange results for large audio files. After putting some effort i found out that the position calculation is going out of limits in android. Though a long type in java has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807, i wondered why my calculation went out of limits.
After going through some posts i found that android support limited value ranges unlike java. But my question is how i can perform this calculation in android? Is there any other android specific data types?
This is the calculation i perform in my app:
position=((bufferSize*currentPosition)/duration);
As noted in my comment, the post you're taking your information from is simply incorrect. long is always 64 bits. There may be some limitations in NIO, but that's a different matter.
However, your problem can easily be explained without any trickery. Here's your code again:
position = (bufferSize * currentPosition) / duration;
You haven't said what the types of bufferSize and currentPosition are, but I'll assume they're long. If you've got a very large buffer and a "late" currentPosition value, it's possible that the result of the multiplication will overflow into a negative number. When you divide that negative number by duration, you'll still get a negative (but smaller in magnitude) number.
If bufferSize and currentPosition are int variables instead of long, that overflow will occur much sooner. Indeed, if that's the case then you may well just be able to fix your problem just by forcing the arithmetic to be done in 64 bits:
position = ((long)bufferSize * currentPosition) / duration;
You should work out what range of currentPosition this would work up to, based on your buffer size - I'd expect it to be fine for any sensibly-sized file length and buffer size combination, to be honest.
If that doesn't help, please post more information - including the variable types and what values you're observing (for all variables, including the results).
Like #Jon Skeet, I guess a long is enough. But in the case a long is not large enough, you could consider divding your bufferSize by a thousand or by a million. You would loose some precision but the result would still be close to what your are looking for : you would approximate your buffer "fullness" in kilobytes or in megabytes instead of its value in bytes.
Hey , i hope i get help with this.
im a coder of a rsps (runescape private server)
and in this game you could like have items and weapons
and the max anmount of a item you can have is 2147000000
and i can change the amount of the max by changing this int
public int maxItemAmount = 2147000000;
and it works
but i want to make it like 3000000000
and i do this
public int maxItemAmount = 3000000000;
and when i compile i get this error
integrer number too large: 3000000000
please guys help me out if you can :)
Integer has an upper bound of 2^31 (2147483648). If you want numbers longer than that, you can use a long or double.
Integers are signed 32-bit values and thus can have a maximum value of 231 = (note that one bit is used for the sign).
You need to change the type of maxItemAmount to long.
you should go for 64 bit types ... i.e: long ...
do ...
public long maxItemAmount = 3000000000L;
A 32-bit signed integer has a range of -232 to 232-1, or − 2,147,483,648 to 2,147,483,647. If you want an integral value outside this range you need to use a 64-bit (long) variable. On the other hand, how likely is it that anyone will have over 2 billion distinct items or weapons? Perhaps, you want to rethink it and keep track of items and their quantities separately. You might also want to consider that changing to use a long may have unexpected consequences if parts of the code assume that it's a 32-bit value.
You can check out the max value of numbers with Integer.MAX_VALUE and Long.MAX_VALUE.
If a long is still not enough for your needs, you can check out the BigInteger class.
Instead of int you should use long. Here you can find more information about the precision of Java primitive data types.
Quoting from the link:
long: The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.
As other people has sayed, you have to use another data type that support big numbers.
I recommend you using long. For example:
public long maxItemAmount = 3000000000L;
Notice the L at the end of the value. It tells the runtime that 3000000000 is a long value. Or use:
public long maxItemAmount = new Long("3000000000");
See more info on this page.
Also, someone commented using a BigInteger. It's like a String; don't have limit.
However, I recommend you to use it rarely. A long will probably suit your needs.
EDIT: Strictly speaking, BigIntegers and Strings have limit (see comments).