Large number division in bash returns wrong result
I'm trying to convert a very large number of bytes into gigabytes.
echo $(( 41003021288998461440 / 1073741824 ))
This returns 3827300985. That is incorrect. The correct answer would be 38187039354. 11 digits versus 10.
Using different 'scale = 30' or piping through bc doesn't change the answer. What am I doing wrong?
As an alternative I tried this:
awk -v var1=41003021288998461440 -v var2=1073741824 'BEGIN { print ( var1 / var2 ) }' OFMT='%25g'
Which returns "3.8187e+10", which seems to be numerically correct, but I then can't figure out how not to get in scientific notation. Printf "%12d" isn't helping because it can't seem to handle the division in a passed parameter.
I suspect fixing the awk scientific notation issue would probably be easier, but I'd still like to know why the long division with echo just returns a completely wrong result. That's very concerning, and since I do calculations in that way frequently, I'd like to know what I need to do to get echo to calculate accurately.
I also know that I fixed the problem once before... but I lost how I did it and can't recall now, sigh.
Solution 1:
Bash integers are not arbitrary precision:
Evaluation is done in fixed-width integers with no check for overflow, though division by 0 is trapped and flagged as an error.
A likely upper limit in modern systems would be 2^63 for signed integers:
$ echo $(( 2**63 - 1 ))
9223372036854775807
$ echo $(( 2**63 ))
-9223372036854775808
$ echo $(( 2**62 ))
4611686018427387904
Your number is waaaay too large (~4x) for that. If you want to do random arbitrary precision arithmetic interactively, use Python:
>>> 41003021288998461440 / 1073741824
38187039353.88332