Pan
Pan

Reputation: 2101

Adding two numbers don't get correct result

I try to add two numbers, but don't get correct result

var n1:Number =  2785077255;
var n2:Number = 100000097214922752;
trace(Number(n1 + n2));//trace 100000100000000000, not 100000100000000007
trace((Number.MAX_VALUE - Number(n1 + n2)) > 100);//trace true

When I got the wrong result, I thought it exceed the Number's max value,so I test it and it doesn't trace false as I thought.

Upvotes: 0

Views: 71

Answers (1)

fsbmain
fsbmain

Reputation: 5267

Yes, the problem is in Number as @Phylogenesis mentioned, it's actually 64 bit double with 52 bits for mantis, but your result exceededs that. The good news are that there is a workaround for that, event two :)

  1. Use some BigInteger/LongInt AS3 impelementation (you can google several of them), for instance BigInteger from as3crypto, or LongInt from lodgamebox

  2. It's currently only for multiplying, but you can modify that solution as a small task. For best performance (without creation of temporary arrays/byte arrays) you can use that utility method that I created once (it's based on LongInt from lodgamebox library)

    /**
     * Safe multiplying of two 32 bits uint without precision lost.  
     * 
     * Usage:
     * Default behaviour (with 64 bit Number mantis overflow): 
     *      uint(1234567890 * 134775813) = 1878152736
     * 
     * Fixed correct result by that method: 
     *      uint(1234567890 * 134775813) = 1878152730
     * 
     * @param val1
     * @param val2
     * @return 
     * 
     */
    public static function multiplyLong(val1:uint, val2:uint):uint
    {
        var resNum:Number = val1*val2;
        //52 bits of mantis in 64 bit double (Number) without loose in precision
        if(resNum <= 0xFFFFFFFFFFFFF)
            return uint(resNum);
    
        //count only low 32 bits of multiplying result 
        var i:uint, mul:Number, ln:uint=0, hn:uint=0, _low:uint = val1;
        for (i = 1<<31; i; i >>>= 1)
        {
            if(val2 & i)
            {
                mul = _low * i;
                ln += mul & uint.MAX_VALUE;
            }
        }
        _low = ln;
    
        return _low;
    }
    

Upvotes: 1

Related Questions