I have a question about big numbers in groovy, I write at script that call to DB and put budget value in variable called toub_start_budget, the value stored is 2570000000.
since I want to do arithmetic operation I created another variable called toub_budget and put in it the value of the first variable as float.
The problem is that the new variable not saved the data as float but as a number as 2.56999987E9.
and the arithmetic that I do are wrong, for example divide by 1000000, will bring 2569.9 and not the accurate results 2570 (accuracy is important).
can someone please advise how to handle big numbers, with arithmetic?
regards
Do not use float, it is by definition inaccurate. If you need to do accurate calculations and arbitrary big numbers, use BigDecimal. If you use Groovy, then just do the calculation, Groovy will automatically use BigDecimal when appropriate as you can see by executing (2570000000 / 1000).getClass() and (2570000000 / 1001).getClass()
Related
How can I calculate in Java any power of a number in a base 2 (2^n, where n can be any number), without using the BigInteger class?
Let's say I got the binary number 100000000000000000000100000000001 stored in a given array, and I want to print its value in a decimal number (just to print it, let's say we store it in a String type).
I'm not sure I understand your problem completely, but if n is the binary number converted to a decimal number, then you are playing with way too large numbers.
Consider the binary number as decimal. Your example would be the decimal number 4294969345. Just try to consider what 2^4294969345 would be. As an example 2^429 would be 1.38633485×10^129. There's no way you can execute this.
I agree with the others, please share your code, and maybe you can get a better answer.
EDIT: If it's just a conversion from the big binary number to a decimalnumber, you can use Long.parseLong(binaryNumber, 2), where binaryNumber is your binary number as a String.
The values needs to be saved somewhere to be "just printed", whether a data structure or a primitive, in your case it's way too large for an integer ( > 2^31), you can use long instead (Long.parseLong(binary, 2)) but eventually if it keeps getting bigger, you will need another way, either using BigInteger or your own brains.
I have a need to sum all of the money from the underlying DB.
I have 2 options to do that.
Use the SQL SUM() function to sum it up or
Get the list of all the money and sum in memory.
I think it would be better to use the first option considering better performance but I want to know if SUM function can be safely used to sum the monetary amount without loosing the precision.
If it were the 2nd option I would have used Java's BigDecimal which is used to represent money.
It depends on the datatype you are using.
if you're using floats, there is some precision lost in mysql (see here and here), if you are using decimals, then you should be ok.
If you use DECIMAL(m, 2) (assuming 2 decimal places for your currency), MySQL's SUM() will be exact and faster than fetching all the rows, shoveling them into the client, then doing the equivalent arithmetic with a similar library.
AVG has precision issues in any situation.
https://msdn.microsoft.com/en-us/library/ms187810.aspx
Returns the summation of all expression values in the most precise expression data type.
SUM will not lose precision any more than your local processor would, you are safe to use it.
Edit:
I mistakenly posted some T-SQL docs, here are the mySQL docs:
http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
The SUM() and AVG() functions return a DECIMAL value for exact-value arguments (integer or DECIMAL), and a DOUBLE value for approximate-value arguments (FLOAT or DOUBLE).
So identically to T-SQL, it will choose the most precise data type.
This question already has answers here:
Why not use Double or Float to represent currency?
(16 answers)
Closed 8 years ago.
it's pretty clear why double & co. are not a good choice when it comes to handling currency.
I'm wondering though, since the issue only arises when calculations are performed on the value, am I correct by assuming that there is no problem at all to just store a currency value in a double?
For example:
1. Value gets loaded from any given source into a double
2. Value gets modified, directly typed in by the user.
3. Value gets stored to disk in a suitable format.
In the above example the double is just a way to store the value in memory, and thus shouldn't present any of the problems that arise if calculates are performed on the value.
Is this correct?
And, if correct, wouldn't it be better to use currency specific types, only when performing calculations?
Instead of loading 1000 BigDecimals from a database one could load 1000 doubles. Then, when necessary, define a BigDecimal, do the calculations and just keep the resulting double in memory.
No, it still causes problems, even if you don't perform any calculations. The problem is that the value you store might not be exactly representable as a double, so even if you just store it and read it back, you might not get back what you stored.
If you store 0.1 in a double, for instance, you'll find it's not actually 0.1 stored at all, because you can't represent 0.1 exactly in binary.
No. A double is never the correct type to store a currency value. Doubles are floating point values, that is, they are basically numbers of the form x * 2^y, where x and y are integers. Thus, some values, such as 0.10 (10 cents) have no exact representation as a double.
The problem here is that when you save say 10.12 in a double variable it may not have a exact double representation, so the java runtime will save it as a closest possible double representation, say 10.1199999999999 or 10.1200000000001 (just an example, I am not sure, have to test). So you get the point, as soon as you put the value in a double variable the currency value is approximated. However, that being said, you can still use a double for calculations and then use appropriate formatting while printing out the values or writing to file, such that the non-significant digits are hidden, depending on your application.
Is there a simple way that i can manipulate high precision decimal numbers in java, without a limit on the number of decimal places, and the ability to output the number in a println or write it to a file? I want to work with one of the identities of PI that involves a sum of fractions, where k starts at 0 and goes to infinity. I know that most systems use limited decimals, but couldn't i use some pre-designed class which stores the value as a linked list of massive memory blocks if the number gets long enough? Please keep in mind i do need to do arithmetic with this class as well. Addition, subtraction, multiplication, and division should be sufficient.
I believe that you are looking for the java.lang.BigDecimal class.
Look at java.lang.BigDecimal, may solve your problem.
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
So long story short I've spent the last 2-3 days trouble shooting a bug in my graphing calculator that arose when I implemented a new window resize listener. The bug was when I resized my window slowly the functions wouldn't be transformed properly and if I moved it fast they would transform just fine. I looked at all of my formulas and algorithms and everything was spot on (the same as it was with my previous window resizing method). Whenever there was a change in width I'd take the difference it changed, divide it by 2 and move the graphs by that amount. Really simple.
double changeX = (newCanvasWidth - canvasWidth)/2;
double changeY = (newCanvasHeight - canvasHeight)/2;
This had worked fine and made all of the logical sense I needed to ignore this as the culprit for nearly 3 days. It was so innocent that I almost rewrote my entire program to try and fix this issue ranging from compensation algorithms to all new methods to predict these errors and fix them. It was becoming a nightmare and was incredibly annoying. Before giving up complete hope I decided to investigate the problem once again using a thorough trace of every single calculation related to this and outputting the results of these calculations and I found something odd. Whenever the difference between (newCanvasWidth - canvasWidth) was odd I was not getting the half at the end of the integer.
So if the difference between them was say 15, changeX would reflect 7. Most troubling is when the difference was 1, changeX would be 0.
Upon discovering this I of course tried the obvious thing and type casted the subtraction.
double changeX = (double)(newCanvasWidth - canvasWidth)/2;
double changeY = (double)(newCanvasHeight - canvasHeight)/2;
And lo and behold my issue was solved!
What I don't understand though is why this didn't happen automatically. Also if this is just something I'm going to have to make accommodations for all of the time where is the limit? Is there anyway to know when you're going to need to type cast simple calculations like this?
Java doesn't automatically expand integral expressions to floating-point because it's very expensive computationally to do so, and because you can lose precision. Yes, if you have an integral value that you want divided into a non-integral quotient, you'll always need to tell Java (and C/C++) that. The Java Language Specification has comprehensive rules about what type of value a math expression is.
A shortcut when using a numeric literal like this is to make the literal a floating-point type:
double changeX = (newCanvasWidth - canvasWidth) / 2.0;
It wasn't happening automatically because the calculation on the right-hand side (RHS) of the assignment, i.e. (newCanvasHeight - canvasHeight)/2 takes place as a separate operation before the assignment to changeY. Since all terms on the RHS are integers, the result is an integer with the decimal part truncated (not rounded), which is then stored as a double (so instead of 7.5 you get 7, which is stored as 7.0). Since you were using a constant term on the RHS, you could make it a double (like #Clown suggested), thereby making the result of the calculation a double before it is stored. If all terms on the RHS were variables, however, then you would cast.
So, yes, there is a way to know when you need to cast (or otherwise convert) in situations like these: when the most precise term of the RHS of the assignment is less precise than the LHS.
Because newCanvasWidth and canvasWidth is declared as int's you don't automatically get a decimal result when dividing with another whole number. If you don't want to cast you should have been using 2.0. Integer division in Java always discard decimals, unless you tell it otherwise.
If the result has a chance of becoming a decimal number, for example when using division, you should always make sure the result is a double. Here you would cast when necessary. But generally speaking, you use type casting a lot more often in different contexts, such as going from Object to something else, or, as an even better example, when going from a View to a TextView in Android.