Solidity – Parsing Strings to Integers for Large Numbers

solidity

I've been trying to find a way to pass integer as string using a few of the function provided by the community but , while it works for " small " numbers it doesn't for larger ones.

Does anybody knows why and what is the limit here ?

contract Test {

    function stringToUint(string s) constant returns (uint) {
    bytes memory b = bytes(s);
    uint result = 0;
    for (uint i = 0; i < b.length; i++) { // c = b[i] was not needed
        if (b[i] >= 48 && b[i] <= 57) {
            result = result * 10 + (uint(b[i]) - 48); // bytes and int are not compatible with the operator -.
        }
    }
    return result; // this was missing
    }

        // parseInt
    function parseInt(string _a)  returns (uint) {
        return parseInt(_a, 0);
    }

    // parseInt(parseFloat*10^_b)
    function parseInt(string _a, uint _b) internal returns (uint) {
        bytes memory bresult = bytes(_a);
        uint mint = 0;
        bool decimals = false;
        for (uint i=0; i<bresult.length; i++){
            if ((bresult[i] >= 48)&&(bresult[i] <= 57)){
                if (decimals){
                   if (_b == 0) break;
                    else _b--;
                }
                mint *= 10;
                mint += uint(bresult[i]) - 48;
            } else if (bresult[i] == 46) decimals = true;
        }
        if (_b > 0) mint *= 10**_b;
        return mint;
    }

}

The first function stringToUint is from this SO ( How to convert string to int )
And the second one is from the OraclizeitAPI contract.

Both don't behave as i expect for this param :

"10000000000000000000000000000000000000000000000000000000000000000000000000000000001"

Will return :

79381376136047024986163664703589883750854290615248988403587492614211165487105

When i'm expecting

10000000000000000000000000000000000000000000000000000000000000000000000000000000001

Best Answer

Your issue is here:

uint result = 0;

The uint type can hold up to 2^256 - 1. In decimal, this is

115792089237316195423570985008687907853269984665640564039457584007913129639935

Note that this is less than double the result you get, which confirms that you've reached the 256 bit limit:

 79381376136047024986163664703589883750854290615248988403587492614211165487105

Your test number is actually 273 bits wide.

If you need to handle integers larger than 256 bits then you're going to have to define some sort of bigInteger type to handle them. I'm not aware of a generic bigInt library for Solidity; you may need to roll your own.

Related Topic