곱셈 C #을 사용하지 않고 문자열을 정수로 변환


9

곱셈을 사용하지 않고 문자열을 정수로 변환하는 방법이 있습니까? int.Parse ()의 구현은 또한 곱셈을 사용합니다. 문자열을 int로 수동으로 변환 할 수있는 다른 유사한 질문이 있지만 기본 10으로 숫자를 곱해야합니다.


3
(텍스트) 또는없는 (제목)?
d4zed

2
당신은 명확히 할 수 있습니까? 당신의 제목은 'with'를 사용하고 텍스트는 'with'를 사용한다고 말합니다
vonludi

1
질문의 나머지 내용을 고려하면 (예를 들어 "숫자에 밑수 10을 곱해야 함") 제목이 정확합니다. 또한 곱셈이 허용되면 사소한 것이므로 묻는 것이 합리적이지 않습니다.
요한

7
이 기사 는 곱셈을 비트 시프트와 덧셈 ( x<<1 + x<<3) 으로 10으로 대체하는 것을 제안 하지만 여전히 곱셈을 사용하는 방법이므로 질문의 "정신"에 있는지 말하기는 어렵습니다 ...
Simon Mᶜ 켄지

3
않습니다 for (int i = 0; i < 10; i++) result += number;계산?
canton7

답변:


12

10 진법으로 가정하고 곱셈을 비트 시프트로 대체하면 ( 여기 참조 ) 이것은 양의 정수에 대한 솔루션이 될 수 있습니다 .

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

    return number;
}

ideone 의 예를 참조하십시오 .

유일한 가정은 문자이다 '0'하는 '9'문자 집합에서 서로 바로 옆에 거짓말. 숫자 문자는를 사용하여 정수 값으로 변환됩니다 character - '0'.

편집하다:

들어 음수 이 버전은 ( 여기 참조 ) 작동합니다.

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;
}

일반적으로 널 검사, 숫자가 아닌 다른 문자의 문제 등과 같은 오류를 고려해야합니다.


6

때에 따라 다르지. 곱셈의 논리적 연산 또는 실제로 하드웨어에서 어떻게 수행되는지에 대해 이야기하고 있습니까?

예를 들어, 16 진 (또는 8 진 또는 다른 2 진 승수) 문자열을 "곱하지 않고"정수로 변환 할 수 있습니다. 문자별로 이동하고 계속해서 ( |) 및 비트 이동 ( <<)을 유지할 수 있습니다 . 이것은 *연산자 사용을 피합니다 .

십진 문자열로 동일한 작업을 수행하는 것이 까다 롭지 만 여전히 간단한 추가가 있습니다. 루프를 사용하여 동일한 작업을 수행 할 수 있습니다. 매우 간단합니다. 또는 당신은 당신의 자신의 "곱셈표"를 만들 수 있습니다-희망적으로 당신은 학교에서 숫자를 곱하는 방법을 배웠습니다; 컴퓨터에서도 같은 일을 할 수 있습니다. 물론 이진이 아닌 10 진수 컴퓨터를 사용하는 경우 이전 16 진 문자열과 마찬가지로 "비트 시프트"를 수행 할 수 있습니다. 심지어 이진 컴퓨터와 함께, 당신은 bitshifts의 시리즈를 사용할 수 있습니다 - (a << 1) + (a << 3)와 동일합니다 a * 2 + a * 8 == a * 10. 음수에주의하십시오. 이것을 흥미롭게 만들기위한 많은 트릭을 알아낼 수 있습니다.

물론, 둘 다 변장에있어서의 곱셈 일뿐입니다. 위치 숫자 시스템은 본질적으로 곱하기 때문 입니다. 이것이 특정 숫자 표현이 작동하는 방식입니다. 이 사실을 숨기는 단순화를 가질 수 있습니다 (예 : 이진수에만 필요 01). 곱하기 대신 간단한 조건을 가질 수 있습니다. 물론 두 가지 가능한 입력과 두 개의 가능한 입력만으로도 실제로 곱셈입니다 출력),하지만 항상 숨어 있습니다. 작업을 수행하는 하드웨어가 더 단순하거나 빠를 수있는 경우에도 <<와 동일 * 2합니다.

곱셈을 완전히 없애려면 위치 시스템을 사용하지 않아야합니다. 예를 들어, 로마 숫자는 첨가제 (- 네 것 실제 로마 숫자는 오늘날 우리가 가지고있는 소형화 규칙을 사용하지 않은 것을 참고있다 IIII, 없다 IV, 그것은 십사은 같은 어떤 형태로 작성 될 수있는 XIIII, IIIIX, IIXII, VVIIII등). 이러한 문자열을 정수로 변환하는 것은 매우 쉽습니다. 문자별로 이동하고 계속 추가하십시오. 문자가 X인 경우 10을 추가하십시오. 인 경우 V5를 추가하십시오. 만약I하나를 추가하십시오. 로마 숫자가 왜 그렇게 오랫동안 인기를 얻었는지 알 수 있기를 바랍니다. 위치 숫자 시스템은 곱셈과 나눗셈을 많이해야 할 때 훌륭합니다. 덧셈과 뺄셈을 주로 다루는 경우 로마 숫자는 훌륭하게 작동하며 학교 교육이 훨씬 적습니다 (그리고 주판은 위치 계산기보다 훨씬 쉽게 만들고 사용할 수 있습니다!).

이와 같은 과제를 통해 면접관이 실제로 기대하는 것에 대한 많은 히트와 누락이 있습니다. 아마도 그들은 단지 당신의 사고 과정을보고 싶어 할 것입니다. 당신은 기술을 포용 합니까 ( 실제로 곱셈 <<은 아님 )? 당신은 숫자 이론과 컴퓨터 과학을 알고 있습니까? 코드로 뛰어 들거나 설명을 요청합니까? 재미난 도전이라고 생각하십니까, 아니면 직업과 관련이없는 말도 안되는 지루한 인터뷰 질문으로 보십니까? 면접관이 찾고있는 답변을 알려주는 것은 불가능합니다.

그러나 나는 적어도 당신에게 가능한 대답을 엿볼 수 있기를 바랍니다 :)


로마 숫자 시스템을 사용하는 경우 로마 숫자 시스템의 일부가 아닌 B, T, S, R, G, A 등과 같은 문자가 있으면 어떻게 추가합니까? 다시 말해, 어떻게 동등한 정수를 얻을 수 있습니까?
Adheesh

@Adheesh 나는 당신이 무엇을 묻고 있는지 전혀 모른다. 문제가 될 것으로 생각되는 예를 들어 줄 수 있습니까?
루안

문자열 "12345"가 있고이를 int로 변환하려고한다고 가정하십시오. 위치 숫자 시스템을 사용하지 않고 로마 숫자 시스템을 사용하려면 어떻게해야합니까? 우리는 어떻게 할 수 있습니까? (나는 곱셈을 전혀 사용하고 싶지 않다)
Adheesh

@Adheesh 로마 숫자 시스템에서 문자열은 "12345"가 아닙니다. 그게 요점입니다. 위치 숫자 시스템은 본질적으로 곱셈입니다. 로마 숫자 체계는 부가 적이다. 로마자 문자열은 "MMMMMMMMMMMMCCCXXXXIIIII"과 같습니다. 문자별로 이동하고 숫자를 계속 추가하십시오.
루안

@Adheesh 물론 ​​실제 현실에서는 그렇게 오래 다루기 힘들지 않을 것입니다. "12345 미터"대신 "XII 킬로 및 CCCXXXXIIIII 미터"또는 이와 유사한 것을 말합니다. 오래된 측정 시스템은 많은 것을 계산할 수없는 사람들에게 적합했습니다. 12 개만 계산할 수 있다면 제국 단위로 표현할 수있는 값의 범위와 현대 단위를 비교하면됩니다 :)
Luaan

5

인터뷰 질문 인 것을 고려할 때 성능이 우선 순위가 높지 않을 수 있습니다. 왜 그냥 :

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.
}

전달 된 문자열이 정수가 아닌 경우, 메소드는 오버 플로우 예외를 발생시킵니다.


1
Brilliant : P 면접관의 즉각적인 피드백이 없다면 사용하지 마십시오. : DI는 동일한 기본 접근 방식을 사용하여 부분 일치로 성능을 향상시킬 수있는 방법이있을 수 있다고 생각합니다. 최소한 음수를 간단히 검사하면 루프의 절반을 절약 할 수 있습니다. 홀수 / 짝 반도 점검.
루안

@Luaan 가능한 한 작은 줄로하고 싶었습니다 :) ...public int StringToInt(string value, int search_from = int.MinValue) => value == search_from.ToString() ? search_from : StringToInt (value, ++search_from);
nl-x

슬프게도, 그것은 폭발 할 것입니다 : D 그러나 그것은 종이에 코드를 작성하는 훌륭한 솔루션입니다-그것은 매우 분명히 정확하고 잘못 작성하기가 어렵습니다. LIINQ-를 사용할 수도 있습니다 Enumerable.Range(int.MinValue, int.MaxValue).First(i => i.ToString() == stringValue.
루안

0

곱셈은 ​​반복 덧셈으로 대체 할 수 있습니다. 따라서 기존 알고리즘의 곱셈을 더하기 만 사용하는 버전으로 바꿀 수 있습니다.

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;
}

이 아이디어를 사용하여 추가 수 (간결하게 생략하기 위해 음수 및 오류 처리 생략)를 최소화하여 특수 문자열을 Int에 작성할 수 있습니다.

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;
}

그러나 성능이 문제가되지 않기 때문에 그만한 가치가 있다고 생각하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.