简体   繁体   中英

Converting String to Integer without using Multiplication C#

Is there a way to convert string to integers without using Multiplication. The implementation of int.Parse() also uses multiplication. I have other similar questions where you can manually convert string to int, but that also requires mulitiplying the number by its base 10. This was an interview question I had in one of interviews and I cant seem to find any answer regarding this.

If you assume a base-10 number system and substituting the multiplication by bit shifts ( see here ) this can be a solution for positive integers .

public int StringToInteger(string value)
{
    int number = 0;
    foreach (var character in value)
        number = (number << 1) + (number << 3) + (character - '0');

    return number;
}

See the example on ideone .

The only assumption is that the characters '0' to '9' lie directly next to each other in the character set. The digit-characters are converted to their integer value using character - '0' .

Edit:

For negative integers this version ( see here ) works.

public static int StringToInteger(string value)
{
    bool negative = false;
    int i = 0;

    if (value[0] == '-')
    {
        negative = true;
        ++i;
    }

    int number = 0;
    for (; i < value.Length; ++i)
    {
        var character = value[i];
        number = (number << 1) + (number << 3) + (character - '0');
    }

    if (negative)
        number = -number;
    return number;
}

In general you should take errors into account like null checks, problems with other non numeric characters, etc.

It depends. Are we talking about the logical operation of multiplication, or how it's actually done in hardware?

For example, you can convert a hexadecimal (or octal, or any other base two multiplier) string into an integer "without multiplication". You can go character by character and keep oring ( | ) and bitshifting ( << ). This avoids using the * operator.

Doing the same with decimal strings is trickier, but we still have simple addition. You can use loops with addition to do the same thing. Pretty simple to do. Or you can make your own "multiplication table" - hopefully you learned how to multiply numbers in school; you can do the same thing with a computer. And of course, if you're on a decimal computer (rather than binary), you can do the "bitshift", just like with the earlier hexadecimal string. Even with a binary computer, you can use a series of bitshifts - (a << 1) + (a << 3) is the same as a * 2 + a * 8 == a * 10 . Careful about negative numbers. You can figure out plenty of tricks to make this interesting.

Of course, both of these are just multiplication in disguise. That's because positional numeric systems are inherently multiplicative . That's how that particular numeric representation works. You can have simplifications that hide this fact (eg binary numbers only need 0 and 1 , so instead of multiplying, you can have a simple condition - of course, what you're really doing is still multiplication, just with only two possible inputs and two possible outputs), but it's always there, lurking. << is the same as * 2 , even if the hardware that does the operation can be simpler and/or faster.

To do away with multiplication entirely, you need to avoid using a positional system. For example, roman numerals are additive (note that actual roman numerals didn't use the compactification rules we have today - four would be IIII , not IV , and it fourteen could be written in any form like XIIII , IIIIX , IIXII , VVIIII etc.). Converting such a string to integer becomes very easy - just go character by character, and keep adding. If the character is X , add ten. If V , add five. If I , add one. I hope you can see why roman numerals remained popular for so long; positional numeric systems are wonderful when you need to do a lot of multiplication and division. If you're mainly dealing with addition and subtraction, roman numerals work great, and require a lot less schooling (and an abacus is a lot easier to make and use than a positional calculator!).

With assignments like this, there's a lot of hit and miss about what the interviewer actually expects. Maybe they just want to see your thought processes. Do you embrace technicalities ( << is not really multiplication)? Do you know number theory and computer science? Do you just plunge on with your code, or ask for clarification? Do you see it as a fun challenge, or as yet another ridiculous boring interview question that doesn't have any relevance to what your job is? It's impossible for us to tell you the answer the interviewer was looking for.

But I hope I at least gave you a glimpse of possible answers :)

Considering it being an interview question, performance might not be a high priority. Why not just:

private int StringToInt(string value)
{
    for (int i = int.MinValue; i <= int.MaxValue; i++)
        if (i.ToString() == value)
            return i;
    return 0; // All code paths must return a value.
}

If the passed string is not an integer, the method will throw an overflow exception.

Any multiplication can be replaced by repeated addition. So you can replace any multiply in an existing algorithm with a version that only uses addition:

static int Multiply(int a, int b)
{
    bool isNegative = a > 0 ^ b > 0;
    int aPositive = Math.Abs(a);
    int bPositive = Math.Abs(b);
    int result = 0;
    for(int i = 0; i < aPositive; ++i)
    {
        result += bPositive;
    }
    if (isNegative) {
        result = -result;
    }
    return result;
}

You could go further and write a specialized String to Int using this idea which minimizes the number of additions (negative number and error handling omitted for brevity):

static int StringToInt(string v)
{
    const int BASE = 10;
    int result = 0;
    int currentBase = 1;
    for (int digitIndex = v.Length - 1; digitIndex >= 0; --digitIndex)
    {
        int digitValue = (int)Char.GetNumericValue(v[digitIndex]);
        int accum = 0;
        for (int i = 0; i < BASE; ++i)
        {
            if (i == digitValue)
            {
                result += accum;
            }
            accum += currentBase;
        }
        currentBase = accum;
    }
    return result;
}

But I don't think that's worth the trouble since performance doesn't seem to be a concern here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM