17

How do i convert a string into a int? here is my code:

   pragma solidity ^0.4.6;

contract MyContract {
    string public a;
    /* Constructor */
    function MyContract() {
        a = "0.12312317314571638713891378174163782169246891247193811231231731";
    }

    function bytesToUInt(uint v) constant returns (uint ret) {
    if (v == 0) {
        ret = 0;
    }
    else {
        while (v > 0) {
            ret = uint(uint(ret) / (2 ** 8));
            ret |= uint(((v % 10) + 48) * 2 ** (8 * 31));
            v /= 10;
        }
    }
    return ret;
}

    function get() constant returns(string){
        return a;
    }
}

7 Answers 7

10

Note that floating point numbers are not supported in Solidity and the Ethereum Virtual Machine at the moment.

While your question is asking about converting a string to an int, your sample code refers to uint rather than int, so I'll provide the solution to convert a string to a uint.

Following is a solution to convert a non-floating point number from a string to a uint (which is a uint256). I've added the solution to this question to my solution to Solidity concatenate uint into a string?:

pragma solidity ^0.4.4;

contract TestIntToString {

    string public uintToStringResult;
    string public appendUintToStringResult;
    uint public stringToUintResult;

    function TestIntToString() {
        uintToStringResult = uintToString(12345678901234567890);
        appendUintToStringResult = appendUintToString("My integer is: ", 1234567890);
        stringToUintResult = stringToUint("12312317314571638713891378174163782169246891247193811231231731");
    }

    function uintToString(uint v) constant returns (string str) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        while (v != 0) {
            uint remainder = v % 10;
            v = v / 10;
            reversed[i++] = byte(48 + remainder);
        }
        bytes memory s = new bytes(i + 1);
        for (uint j = 0; j <= i; j++) {
            s[j] = reversed[i - j];
        }
        str = string(s);
    }

    function appendUintToString(string inStr, uint v) constant returns (string str) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        while (v != 0) {
            uint remainder = v % 10;
            v = v / 10;
            reversed[i++] = byte(48 + remainder);
        }
        bytes memory inStrb = bytes(inStr);
        bytes memory s = new bytes(inStrb.length + i + 1);
        uint j;
        for (j = 0; j < inStrb.length; j++) {
            s[j] = inStrb[j];
        }
        for (j = 0; j <= i; j++) {
            s[j + inStrb.length] = reversed[i - j];
        }
        str = string(s);
    }

    function stringToUint(string s) constant returns (uint result) {
        bytes memory b = bytes(s);
        uint i;
        result = 0;
        for (i = 0; i < b.length; i++) {
            uint c = uint(b[i]);
            if (c >= 48 && c <= 57) {
                result = result * 10 + (c - 48);
            }
        }
    }
}

And here's the Browser Solidity screenshot showing the solution works:

enter image description here

4
  • When converting a string to uInt, uint c = uint(b[i]); should be inside the if conditional, in case someone tries to pass a non-integer as an argument. The if should test the b[i]. Jun 15, 2017 at 8:12
  • Also, in uInt to string, bytes memory s = new bytes(i + 1); is incorrect. Instead, bytes memory s = new bytes(i); with reversed[i - j - 1] is correct. Jun 15, 2017 at 9:08
  • Lastly, your code fails because the docs say Index access: If x is of type bytesI, then x[k] for 0 <= k < I returns the k th byte (read-only). So you cannot overwrite a byte array. DO NOT use this code. Jun 15, 2017 at 11:10
  • Thanks for reviewing and providing an alternative solution. Jun 15, 2017 at 17:35
6

Some of BokkyPooBah's code is incorrect.

Here are the functions to convert uInt to string, and vice versa, along with my comments:

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
}

function uintToString(uint v) constant returns (string) {
    uint maxlength = 100;
    bytes memory reversed = new bytes(maxlength);
    uint i = 0;
    while (v != 0) {
        uint remainder = v % 10;
        v = v / 10;
        reversed[i++] = byte(48 + remainder);
    }
    bytes memory s = new bytes(i); // i + 1 is inefficient
    for (uint j = 0; j < i; j++) {
        s[j] = reversed[i - j - 1]; // to avoid the off-by-one error
    }
    string memory str = string(s);  // memory isn't implicitly convertible to storage
    return str;
}
4

For Solidity 0.8.6

function stringToUint(string memory s) public pure returns (uint) {
        bytes memory b = bytes(s);
        uint result = 0;
        for (uint256 i = 0; i < b.length; i++) {
            uint256 c = uint256(uint8(b[i]));
            if (c >= 48 && c <= 57) {
                result = result * 10 + (c - 48);
            }
        }
        return result;
    }
2

Someone posted the way the Oraclize library converts a string to uint here: http://remebit.com/converting-strings-to-integers-in-solidity/

There is a parseInt() function in the base Oraclize API Contract.

2
  • Is using oraclize recommended in 2018? Nov 14, 2018 at 20:55
  • Copying this function from the Oraclize contract doesn't mean you're relying on Oraclize so I don't believe it matters. On the topic of whether or not Oraclize is recommended, this is probably best asked as an independent question.
    – willjgriff
    Nov 15, 2018 at 12:02
1

library ConvertStringToUint {

function stringToUint(string _amount) internal constant returns (uint result) {
    bytes memory b = bytes(_amount);
    uint i;
    uint counterBeforeDot;
    uint counterAfterDot;
    result = 0;
    uint totNum = b.length;
    totNum--;
    bool hasDot = false;

    for (i = 0; i < b.length; i++) {
        uint c = uint(b[i]);

        if (c >= 48 && c <= 57) {
            result = result * 10 + (c - 48);
            counterBeforeDot ++;
            totNum--;
        }

        if(c == 46){
            hasDot = true;
            break;
        }
    }

    if(hasDot) {
        for (uint j = counterBeforeDot + 1; j < 18; j++) {
            uint m = uint(b[j]);

            if (m >= 48 && m <= 57) {
                result = result * 10 + (m - 48);
                counterAfterDot ++;
                totNum--;
            }

            if(totNum == 0){
                break;
            }
        }
    }
     if(counterAfterDot < 18){
         uint addNum = 18 - counterAfterDot;
         uint multuply = 10 ** addNum;
         return result = result * multuply;
     }

     return result;
}

}

0
0

Oraclize API has parseInt(): https://github.com/oraclize/ethereum-api/blob/master/lib-experimental/oraclizeAPI.lib.sol.

0

I've written better code to handle bytes convert with offset and length. The good point is, It's keep bytes order.

/**
* Convert bytes to uint
* @param _data bytes Byte array
* @param _offset uint256 Position to convert 
* @param _length uint256 Data length
*/
function toUint(bytes _data, uint256 _offset, uint256 _length)
internal pure
returns(uint256 _result) {
    require(_offset >= 0);
    require(_length > 0);
    require((_offset + _length) <= _data.length);
    uint256 _segment = _offset + _length;
    uint256 count = 0;
    for (uint256 i = _segment; i > _offset ; i--) {
        _result |= uint256(_data[i-1]) << ((count++)*8);
    }
}
1
  • TypeError: Explicit type conversion not allowed from "bytes1" to "uint256"
    – Jim
    May 18, 2022 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.