*, /, +,-, % 연산자를 사용하지 않고 숫자를 3으로 나눕니다.


685

어떻게 사용하지 않고 3으로 번호를 나누는 것 *, /, +, -, %, 연산자?

숫자는 부호가 있거나 부호가 없을 수 있습니다.


13
@AlexandreC. -이러한 기술은 더하기 (+)를 사용하고 있습니다.
도끼-SOverflow로 완료 됨

19
이것은 오라클이므로 오라클의 어떤 부분을 사용할 수 있습니까?
Hogan

8
식별 된 중복은 중복되지 않습니다. 이 질문은 솔루션을 해당 작업으로 제한하지 않기 때문에 여기에 여러 대답이 비트 이동이나 덧셈을 사용하지 않습니다.
Michael Burr

66
... PL / SQL의 탄생 방식은 다음과 같습니다.
Sedat Kapanoglu

22
이 질문은 SO의 주제입니다. codegolf.stackexchange.com
Kromster

답변:


548

원하는 작업을 수행 하는 간단한 기능 입니다. 그러나 +연산자 가 필요 하므로 비트 연산자로 값을 추가하기 만하면됩니다.

// replaces the + operator
int add(int x, int y)
{
    while (x) {
        int t = (x & y) << 1;
        y ^= x;
        x = t;
    }
    return y;
}

int divideby3(int num)
{
    int sum = 0;
    while (num > 3) {
        sum = add(num >> 2, sum);
        num = add(num >> 2, num & 3);
    }
    if (num == 3)
        sum = add(sum, 1);
    return sum; 
}

Jim은 다음과 같은 이유로이 작업을 설명했습니다.

  • n = 4 * a + b
  • n / 3 = a + (a + b) / 3
  • 그래서 sum += a, n = a + b그리고 반복

  • 언제 a == 0 (n < 4), sum += floor(n / 3);즉 1,if n == 3, else 0


96
이것은 아마도 오라클이 찾고있는 대답 일 것입니다. +,-, * 및 / 연산자가 실제로 CPU에서 어떻게 구현되는지 간단한 비트 단위 연산을 보여줍니다.
craig65535

21
이것은 n = 4a + b, n / 3 = a + (a + b) / 3이므로 합 + = a, n = a + b 및 반복하기 때문에 작동합니다. a == 0 일 때 (n <4), 합 + = 층 (n / 3); 즉, n == 3이면 1, 그렇지 않으면 0.
Jim Balter

7
여기 내가 찾은 트릭이 비슷한 솔루션을 얻었습니다. 10 진수 : 1 / 3 = 0.333333에서 반복되는 숫자는을 사용하여 쉽게 계산할 수 a / 3 = a/10*3 + a/100*3 + a/1000*3 + (..)있습니다. 바이너리에서 거의 동일합니다 : 1 / 3 = 0.0101010101 (base 2)에있는 리드 a / 3 = a/4 + a/16 + a/64 + (..). 4로 나누면 비트 시프트가 시작됩니다. 우리는 정수만 가지고 있기 때문에 num == 3에 대한 마지막 점검이 필요합니다.
Yorick Sijsling

4
기본 4에서는 더 좋아 a / 3 = a * 0.111111 (base 4) = a * 4^-1 + a * 4^-2 + a * 4^-3 + (..) = a >> 2 + a >> 4 + a >> 6 + (..)집니다.. 밑면 4는 왜 끝에 3 만 반올림하는지 설명하고 1과 2는 반올림 할 수 있습니다.
Yorick Sijsling

2
@ while1 : 비트 단위 AND 연산입니다. 또한 잘 알려진 사실은 n == 2^k다음과 같은 경우에 해당합니다. x % n == x & (n-1)따라서 허용되지 않는 동안 여기 num & 3에서 수행 num % 4하는 데 사용됩니다 %.
aplavin

436

이디 오 상태는 이디 오 솔루션을 요구합니다.

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE * fp=fopen("temp.dat","w+b");
    int number=12346;
    int divisor=3;
    char * buf = calloc(number,1);
    fwrite(buf,number,1,fp);
    rewind(fp);
    int result=fread(buf,divisor,number,fp);
    printf("%d / %d = %d", number, divisor, result);
    free(buf);
    fclose(fp);
    return 0;
}

소수 부분이 필요 또한, 그냥 선언 result으로 double하고 여기에 결과를 추가합니다 fmod(number,divisor).

작동 방식에 대한 설명

  1. fwrite쓰기 용 number바이트 (숫자는 상기 예에서 123456이다).
  2. rewind 파일 포인터를 파일 앞쪽으로 재설정합니다.
  3. fread파일에서 길이 number가 최대 인 "레코드"를 divisor읽고 읽은 요소 수를 반환합니다.

30 바이트를 쓴 다음 3 단위로 파일을 다시 읽으면 10 개의 "단위"가 표시됩니다. 30/3 = 10


13
@earlNameless : 내부에서 무엇을 사용하는지 모르는 "구현 정의"의 블랙 박스에 있습니다. 비트 연산자를 사용하는 것을 막는 것은 없습니다. 어쨌든, 그들은 내 코드의 도메인 외부에 있으므로 내 문제가 아닙니다. :)
Matteo Italia

8
@IvoFlipse는 깨끗하게 정리할 수 있으며, 큰 것을 가져다가 너무 작은 것으로 세 번 밀고 들어가면 얼마의 크기인지 알 수 있습니다 .
Pureferret

27
우리 회사의 최고의 C 프로그래머 (그리고 가장 사회적으로 어색한)에게 코드를 설명하도록 요청했습니다. 그가 그 후, 나는 그것이 매우 독창적이라고 말했다. 그는 '이 잔해는 해결책이 아니다'라고 말하고 책상을 떠나라고 요청했다
cvursache

6
@ cvursache 요점은 질문이 너무 죽어서 뇌가 죽은 대답이 허용된다는 것입니다. "귀사에서"최고의 C 프로그래머 "는"난파는 (적절한) 질문이 아닙니다 "라고 쉽게 말했을 수 있습니다.
JeremyP

17
@JeremyP : 정확히. 내 요점은 실제 생활에서 산술을 지원하지 않고 컴파일러를 받았다면 그 조건에서 작업 하는 것이 의미가 없기 때문에 더 좋은 컴파일러를 요구하는 것이 현명한 것입니다 . 면접관이 비트 단위 연산으로 나눗셈을 구현하는 방법에 대한 나의 지식을 확인하기를 원한다면 그는 간단하고 이론적 인 질문으로 할 수 있습니다. 이런 종류의 "트릭 연습"은 이와 같은 대답을 위해 비명을 지 릅니다.
Matteo Italia

306
log(pow(exp(number),0.33333333333333333333)) /* :-) */

2
제대로 반올림되고 숫자가 너무 크지 않으면 실제로 작동 할 수 있습니다.
신비주의

252
개선 된 버전 : log (pow (exp (number), sin (atan2 (1, sqrt (8)))))
Alan Curry

@bitmask, 수학 함수는 일반적으로 asm에서 직접 구현됩니다.
SingerOfTheFall

7
방금 js 콘솔에 입력했는데 709보다 큰 숫자 (내 시스템 일 수도 있음) Math.log(Math.pow(Math.exp(709),0.33333333333333333333))와 작동하지 않습니다.Math.log(Math.pow(Math.exp(709),Math.sin(Math.atan2(1,Math.sqrt(8)))))
Shaheer

208
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{

    int num = 1234567;
    int den = 3;
    div_t r = div(num,den); // div() is a standard C function.
    printf("%d\n", r.quot);

    return 0;
}

113

예를 들어 x86의 경우 (플랫폼 종속) 인라인 어셈블리를 사용할 수 있습니다. (음수에도 적용됨)

#include <stdio.h>

int main() {
  int dividend = -42, divisor = 5, quotient, remainder;

  __asm__ ( "cdq; idivl %%ebx;"
          : "=a" (quotient), "=d" (remainder)
          : "a"  (dividend), "b"  (divisor)
          : );

  printf("%i / %i = %i, remainder: %i\n", dividend, divisor, quotient, remainder);
  return 0;
}

2
@JeremyP는 C로 답변을 쓸 수 없다는 가정에 대한 귀하의 의견에 실패하지 않습니까? 질문은 결국 "C"로 태그됩니다.
세스 카네기

1
@ SethCarnegie C로 작성된 답이 내 요점입니다. x86 어셈블러는 표준의 일부가 아닙니다.
JeremyP

1
@JeremyP는 사실이지만 asm지시어는 사실 입니다. 그리고 C 컴파일러는 인라인 어셈블러가있는 유일한 컴파일러가 아니라고 델파이도 마찬가지입니다.
세스 카네기

7
@SethCarnegie asm지시문은 부록 J-공통 확장명 아래 C99 표준에만 언급되어 있습니다.
JeremyP

2
arm-eabi-gcc에서 실패합니다.
Damian Yerrick

106

itoa 를 사용하여 밑줄 3 문자열로 변환 하십시오 . 마지막 trit를 버리고 base 10으로 다시 변환하십시오.

// Note: itoa is non-standard but actual implementations
// don't seem to handle negative when base != 10.
int div3(int i) {
    char str[42];
    sprintf(str, "%d", INT_MIN); // Put minus sign at str[0]
    if (i>0)                     // Remove sign if positive
        str[0] = ' ';
    itoa(abs(i), &str[1], 3);    // Put ternary absolute value starting at str[1]
    str[strlen(&str[1])] = '\0'; // Drop last digit
    return strtol(str, NULL, 3); // Read back result
}

4
@cshemby 나는 실제로 그것이 itoa임의의 기초를 사용할 수 있다는 것을 몰랐습니다 . 당신이 사용하여 완전한 작업 구현을 수행한다면 itoa나는 공감할 것이다.
신비주의

2
구현 내용은 다음 /과 같습니다. %... :-)
R .. GitHub STOP HELPING ICE

2
@R .. printf십진 결과 표시 를 위한 구현도 마찬가지 입니다.
Damian Yerrick

57

(참고 : 더 나은 버전을 보려면 아래 편집 2를 참조하십시오!)

"[..] +[..] 연산자 를 사용하지 않고"라고 말했기 때문에이 방법은 까다 롭지 않습니다 . +문자를 함께 사용하는 것을 금지하려면 아래를 참조하십시오 .

unsigned div_by(unsigned const x, unsigned const by) {
  unsigned floor = 0;
  for (unsigned cmp = 0, r = 0; cmp <= x;) {
    for (unsigned i = 0; i < by; i++)
      cmp++; // that's not the + operator!
    floor = r;
    r++; // neither is this.
  }
  return floor;
}

그럼 그냥 말을 div_by(100,3)나누기에 100의해 3.


편집 : 계속해서 ++연산자를 교체 할 수 있습니다 .

unsigned inc(unsigned x) {
  for (unsigned mask = 1; mask; mask <<= 1) {
    if (mask & x)
      x &= ~mask;
    else
      return x & mask;
  }
  return 0; // overflow (note that both x and mask are 0 here)
}

편집 2 : 포함 된 연산자 사용하지 않고 약간 빠른 버전 +, -, *, /, % .

unsigned add(char const zero[], unsigned const x, unsigned const y) {
  // this exploits that &foo[bar] == foo+bar if foo is of type char*
  return (int)(uintptr_t)(&((&zero[x])[y]));
}

unsigned div_by(unsigned const x, unsigned const by) {
  unsigned floor = 0;
  for (unsigned cmp = 0, r = 0; cmp <= x;) {
    cmp = add(0,cmp,by);
    floor = r;
    r = add(0,r,1);
  }
  return floor;
}

구문 이 동일한 함수 매개 변수 목록을 제외하고 add*문자 를 사용하지 않고 포인터 유형을 표시 할 수 없으므로 함수 의 첫 번째 인수를 사용합니다 .type[]type* const

FWIW, AndreyT가0x55555556 제안한 트릭을 사용하기 위해 비슷한 트릭을 사용하여 곱셈 함수를 쉽게 구현할 수 있습니다 .

int mul(int const x, int const y) {
  return sizeof(struct {
    char const ignore[y];
  }[x]);
}

5
Oracle이 언급되었지만 질문 에는 SQL이 아닌 c 태그가 지정 됩니다.
비트 마스크

3
이것은 실제로 SQL처럼 보이지 않습니다!
moooeeeep

64
사용할 수있는 경우 ++: 왜 간단하게 사용하지 /=않습니까?
qwertz

5
@bitmask : ++는 바로 가기이기도합니다. For num = num + 1.
qwertz

4
@bitmask 네,하지만 +=마침내 바로 가기입니다 num = num + 1.
qwertz

44

Setun 컴퓨터 에서 쉽게 가능 합니다 .

정수를 3으로 나누려면 오른쪽으로 1 자리 이동하십시오 .

그래도 그러한 플랫폼에서 적합한 C 컴파일러를 구현할 수 있는지 확실하지 않습니다. "최소 8 비트"를 "최소한 정수를 -128에서 +127까지 보유 할 수있는"것으로 해석하는 것과 같이 규칙을 약간 확장해야 할 수도 있습니다.


8
문제는 C에 "1 자리 오른쪽으로 시프트"연산자가 없다는 것입니다. >>연산자는 "2 ^ n으로 나누기"연산자입니다. 즉, 기계 표현이 아니라 산술로 지정됩니다.
R .. GitHub 중지 지원 얼음

Setun 컴퓨터는 어떤 의미에서든 바이너리가 아니므로 명령어 세트가 반드시 달라야합니다. 그러나 나는 그 컴퓨터의 작동에 전혀 익숙하지 않으므로 응답이 실제로 올바른지 확인할 수는 없지만 적어도 의미가 있으며 독창적입니다. +1
virolino 2019

32

Oracle에서 왔으므로 사전 계산 된 답변의 조회 테이블은 어떻습니까? :-디


32

내 해결책은 다음과 같습니다.

public static int div_by_3(long a) {
    a <<= 30;
    for(int i = 2; i <= 32 ; i <<= 1) {
        a = add(a, a >> i);
    }
    return (int) (a >> 32);
}

public static long add(long a, long b) {
    long carry = (a & b) << 1;
    long sum = (a ^ b);
    return carry == 0 ? sum : add(carry, sum);
}

먼저

1/3 = 1/4 + 1/16 + 1/64 + ...

이제 나머지는 간단합니다!

a/3 = a * 1/3  
a/3 = a * (1/4 + 1/16 + 1/64 + ...)
a/3 = a/4 + a/16 + 1/64 + ...
a/3 = a >> 2 + a >> 4 + a >> 6 + ...

이제 우리가해야 할 일은 비트 시프트 된 값을 합산하는 것입니다! 죄송합니다! 우리는 추가 할 수 없으므로 대신 비트 연산자를 사용하여 추가 기능을 작성해야합니다! 비트 단위 연산자에 익숙하다면 내 솔루션은 상당히 단순 해 보일 것입니다 ...하지만 그렇지 않은 경우에는 예제를 살펴 보겠습니다.

주목해야 할 또 다른 사항은 먼저 30을 왼쪽으로 이동한다는 것입니다! 이것은 분수가 반올림되지 않도록하기위한 것입니다.

11 + 6

1011 + 0110  
sum = 1011 ^ 0110 = 1101  
carry = (1011 & 0110) << 1 = 0010 << 1 = 0100  
Now you recurse!

1101 + 0100  
sum = 1101 ^ 0100 = 1001  
carry = (1101 & 0100) << 1 = 0100 << 1 = 1000  
Again!

1001 + 1000  
sum = 1001 ^ 1000 = 0001  
carry = (1001 & 1000) << 1 = 1000 << 1 = 10000  
One last time!

0001 + 10000
sum = 0001 ^ 10000 = 10001 = 17  
carry = (0001 & 10000) << 1 = 0

Done!

어릴 적 배운 것만 더하면됩니다!

111
 1011
+0110
-----
10001

방정식의 모든 항을 추가 할 수 없기 때문에이 구현이 실패했습니다 .

a / 3 = a/4 + a/4^2 + a/4^3 + ... + a/4^i + ... = f(a, i) + a * 1/3 * 1/4^i
f(a, i) = a/4 + a/4^2 + ... + a/4^i

reslut div_by_3(a)= x를 가정 한 다음을 가정하십시오 x <= floor(f(a, i)) < a / 3. 때 a = 3k, 우리는 오답을 얻는다.


2
3의 입력에 작동합니까? 1/4, 1/16, ... 3은 모두 0을 반환하므로 합계는 0이지만 3/3 = 1입니다.
도끼-SOverflow로 완료 됨

1
논리는 좋지만 구현에 문제가 있습니다. 시리즈 근사값 n/3은 항상보다 작습니다 n/3. 즉 n=3k, 결과에 대해 k-1대신 표시됩니다 k.
Xyand

@Albert, 이것은 몇 가지 변형으로 내가 시도한 첫 번째 접근 방식이지만 모두 3으로 나눌 수 있거나 2로 나눌 수있는 특정 숫자에서 실패했습니다 (변이에 따라 다름). 그래서 더 간단한 것을 시도했습니다. 어디에서 문제가 발생했는지 확인하기 위해이 접근법의 구현을보고 싶습니다.
도끼-SOverflow로 완료 됨

@ hatchet, 질문이 마감되어 새 답변을 게시 할 수 없지만 아이디어는 이진 div를 구현하는 것입니다. 쉽게 찾을 수 있어야합니다.
Xyand


25

32 비트 숫자를 3으로 나누려면 숫자를 곱한 0x55555556다음 64 비트 결과의 상위 32 비트를 취할 수 있습니다.

이제해야 할 일은 비트 연산과 시프트를 사용하여 곱셈을 구현하는 것입니다.


1
이것은 느린 분할을 해결하는 일반적인 컴파일러 트릭입니다. 그러나 0x55555556 / 2 ** 32가 정확히 1/3이 아니기 때문에 약간의 수정을해야 할 수도 있습니다.
코드 InChaos

multiply it. 금지 된 *연산자를 사용하는 것을 의미하지 않습니까?
luiscubal

8
@ luiscubal : 아뇨. "내가해야 할 일은 비트 연산과 시프트를 사용하여 곱셈을 구현하는 것
뿐이다

18

또 다른 해결책. 이것은 하드 코딩 된 예외로 처리 해야하는 int의 최소값을 제외하고 모든 음수 (음수 정수 포함)를 처리해야합니다. 이것은 기본적으로 빼기로 나누지 만 비트 연산자 (shift, xor 및 &) 만 사용합니다. 더 빠른 속도를 위해 3 *를 뺍니다 (감소 력 2). C #에서는 밀리 초당 약 444 개의 DivideBy3 호출 (1,000,000 나누기의 경우 2.2 초)을 실행하므로 끔찍하게 느리지는 않지만 단순한 x / 3만큼 빠르지는 않습니다. 이에 비해 Coodey의 훌륭한 솔루션은이 솔루션보다 약 5 배 빠릅니다.

public static int DivideBy3(int a) {
    bool negative = a < 0;
    if (negative) a = Negate(a);
    int result;
    int sub = 3 << 29;
    int threes = 1 << 29;
    result = 0;
    while (threes > 0) {
        if (a >= sub) {
            a = Add(a, Negate(sub));
            result = Add(result, threes);
        }
        sub >>= 1;
        threes >>= 1;
    }
    if (negative) result = Negate(result);
    return result;
}
public static int Negate(int a) {
    return Add(~a, 1);
}
public static int Add(int a, int b) {
    int x = 0;
    x = a ^ b;
    while ((a & b) != 0) {
        b = (a & b) << 1;
        a = x;
        x = a ^ b;
    }
    return x;
}

이것은 내가 편리했던 것이기 때문에 c #이지만 c와의 차이는 적어야합니다.


빼기를 한 번 빼기 만하면됩니다. 두 번 빼면 이전보다 두 배 더 큰 이전 반복을 빼기 때문입니다.
Neil

(a >= sub)빼기로 계산 됩니까 ?
Neil

@ Neil, 당신이 옳을 것 같아요. 내부 while은 간단한 if로 대체 될 수있어 루프의 두 번째 반복에서 불필요한 비교를 저장합니다. > = 빼기에 관해서는 ... 그렇지 않기를 바랍니다. 나는 당신의 요점을 보지만,> =는 뺄셈으로 간주되지 않는쪽에 기댈 것이라고 생각합니다.
도끼-SOverflow로 완료 됨

@ Neil, 나는 그 변화를 만들었고, 시간을 반으로 줄였습니다 (또한 불필요한 Negates를 구했습니다).
도끼-SOverflow로 완료 됨

16

정말 쉽습니다.

if (number == 0) return 0;
if (number == 1) return 0;
if (number == 2) return 0;
if (number == 3) return 1;
if (number == 4) return 1;
if (number == 5) return 1;
if (number == 6) return 2;

(물론 간결하게하기 위해 일부 프로그램을 생략했습니다.) 프로그래머가이 모든 것을 입력하는 데 지치면 프로그래머가 별도의 프로그램을 작성하여 생성 할 수 있다고 확신합니다. 나는 /자신의 일을 엄청나게 단순화 시키는 특정 운영자를 알고 있다.


8
당신은을 사용할 수 Dictionary<number, number>반복 대신에 if당신이 할 수 있도록 문 O(1)시간 복잡도를!
피터 올슨

@EnesUnal 아니요, 시간이 점점 더 많은 if 문을 통과해야하기 때문에 숫자가 증가함에 따라 시간이 선형으로 증가합니다.
피터 올슨

Theoritically이 :) 증가하지 않는다
totten

내가 switch 문을 사용하는 경우 @PeterOlson는 EresUnal, 그것은 O (1) :-) 것
thedayturns

또는 배열을 생성하고 동적 프로그래밍을 사용할 수 있습니다. x / 3 = y이면 y << 2 + y = x-x % 3입니다.
lsiebert

14

카운터 사용은 기본 솔루션입니다.

int DivBy3(int num) {
    int result = 0;
    int counter = 0;
    while (1) {
        if (num == counter)       //Modulus 0
            return result;
        counter = abs(~counter);  //++counter

        if (num == counter)       //Modulus 1
            return result;
        counter = abs(~counter);  //++counter

        if (num == counter)       //Modulus 2
            return result;
        counter = abs(~counter);  //++counter

        result = abs(~result);    //++result
    }
}

모듈러스 기능을 수행하기도 쉽고, 주석을 확인하십시오.


@Enes Unal : 적은 숫자가 아닙니다 :)이 알고리즘은 매우 기본적입니다.
GJ.

모든 원시성은 약점 : 포함
totten

11

이것은 기본 2의 클래식 분할 알고리즘입니다.

#include <stdio.h>
#include <stdint.h>

int main()
{
  uint32_t mod3[6] = { 0,1,2,0,1,2 };
  uint32_t x = 1234567; // number to divide, and remainder at the end
  uint32_t y = 0; // result
  int bit = 31; // current bit
  printf("X=%u   X/3=%u\n",x,x/3); // the '/3' is for testing

  while (bit>0)
  {
    printf("BIT=%d  X=%u  Y=%u\n",bit,x,y);
    // decrement bit
    int h = 1; while (1) { bit ^= h; if ( bit&h ) h <<= 1; else break; }
    uint32_t r = x>>bit;  // current remainder in 0..5
    x ^= r<<bit;          // remove R bits from X
    if (r >= 3) y |= 1<<bit; // new output bit
    x |= mod3[r]<<bit;    // new remainder inserted in X
  }
  printf("Y=%u\n",y);
}

10

파스칼로 프로그램을 작성하고 DIV연산자를 사용하십시오 .

질문에 태그가 붙어 있기 때문에 파스칼로 함수를 작성하고 C 프로그램에서 함수를 호출 할 수 있습니다. 그렇게하는 방법은 시스템마다 다릅니다.

그러나 Free Pascal fp-compiler패키지가 설치된 Ubuntu 시스템에서 작동하는 예제가 있습니다 . (나는 잘못 배치 된 고집에서 이것을하고 있습니다. 나는 이것이 유용하다고 주장하지 않습니다.)

divide_by_3.pas :

unit Divide_By_3;
interface
    function div_by_3(n: integer): integer; cdecl; export;
implementation
    function div_by_3(n: integer): integer; cdecl;
    begin
        div_by_3 := n div 3;
    end;
end.

main.c :

#include <stdio.h>
#include <stdlib.h>

extern int div_by_3(int n);

int main(void) {
    int n;
    fputs("Enter a number: ", stdout);
    fflush(stdout);
    scanf("%d", &n);
    printf("%d / 3 = %d\n", n, div_by_3(n));
    return 0;
}

짓다:

fpc divide_by_3.pas && gcc divide_by_3.o main.c -o main

샘플 실행 :

$ ./main
Enter a number: 100
100 / 3 = 33

8
int div3(int x)
{
  int reminder = abs(x);
  int result = 0;
  while(reminder >= 3)
  {
     result++;

     reminder--;
     reminder--;
     reminder--;
  }
  return result;
}

3
++ 및-연산자는 + 및-연산자와 다릅니다! 어셈블리 언어에는 두 개의 명령어가 ADD있으며 INC동일한 opcode가 없습니다.
Amir Saniyan

7

이 답변이 이미 게시되어 있는지 확인하지 않았습니다. 프로그램을 부동 숫자로 확장해야하는 경우 숫자에 필요한 10 * 정밀도를 곱한 후 다음 코드를 다시 적용 할 수 있습니다.

#include <stdio.h>

int main()
{
    int aNumber = 500;
    int gResult = 0;

    int aLoop = 0;

    int i = 0;
    for(i = 0; i < aNumber; i++)
    {
        if(aLoop == 3)
        {
           gResult++;
           aLoop = 0;
        }  
        aLoop++;
    }

    printf("Reulst of %d / 3 = %d", aNumber, gResult);

    return 0;
}

7

이것은 세 개뿐만 아니라 모든 제수에게도 효과가 있습니다. 현재는 서명되지 않은 사용자에게만 해당하지만 서명 된 것으로 확장하는 것이 그렇게 어렵지 않아야합니다.

#include <stdio.h>

unsigned sub(unsigned two, unsigned one);
unsigned bitdiv(unsigned top, unsigned bot);
unsigned sub(unsigned two, unsigned one)
{
unsigned bor;
bor = one;
do      {
        one = ~two & bor;
        two ^= bor;
        bor = one<<1;
        } while (one);
return two;
}

unsigned bitdiv(unsigned top, unsigned bot)
{
unsigned result, shift;

if (!bot || top < bot) return 0;

for(shift=1;top >= (bot<<=1); shift++) {;}
bot >>= 1;

for (result=0; shift--; bot >>= 1 ) {
        result <<=1;
        if (top >= bot) {
                top = sub(top,bot);
                result |= 1;
                }
        }
return result;
}

int main(void)
{
unsigned arg,val;

for (arg=2; arg < 40; arg++) {
        val = bitdiv(arg,3);
        printf("Arg=%u Val=%u\n", arg, val);
        }
return 0;
}

7

및 문자열 연결 /을 사용하여 "장면 뒤에서"연산자 를 사용하는 것이 부정적 eval입니까?

예를 들어, Javacript에서는 다음을 수행 할 수 있습니다.

function div3 (n) {
    var div = String.fromCharCode(47);
    return eval([n, div, 3].join(""));
}

7

PHP 에서 BC Math 사용하기 :

<?php
    $a = 12345;
    $b = bcdiv($a, 3);   
?>

MySQL (Oracle의 인터뷰)

> SELECT 12345 DIV 3;

파스칼 :

a:= 12345;
b:= a div 3;

x86-64 어셈블리 언어 :

mov  r8, 3
xor  rdx, rdx   
mov  rax, 12345
idiv r8

1
멋진 이야기, 이것은 C로 태그되었고 첫날부터 그렇게되었습니다. 또한 질문의 요점을 완전히 파악하지 못합니다.
Lundin

6

먼저 내가 생각해 냈습니다.

irb(main):101:0> div3 = -> n { s = '%0' + n.to_s + 's'; (s % '').gsub('   ', ' ').size }
=> #<Proc:0x0000000205ae90@(irb):101 (lambda)>
irb(main):102:0> div3[12]
=> 4
irb(main):103:0> div3[666]
=> 222

편집 : 죄송합니다, 태그를 눈치 채지 못했습니다 C. 그러나 문자열 형식에 대한 아이디어를 사용할 수 있습니다.


5

다음 스크립트는 연산자를 사용하지 않고 문제를 해결하는 C 프로그램을 생성합니다 * / + - %.

#!/usr/bin/env python3

print('''#include <stdint.h>
#include <stdio.h>
const int32_t div_by_3(const int32_t input)
{
''')

for i in range(-2**31, 2**31):
    print('    if(input == %d) return %d;' % (i, i / 3))


print(r'''
    return 42; // impossible
}
int main()
{
    const int32_t number = 8;
    printf("%d / 3 = %d\n", number, div_by_3(number));
}
''')


4

이 접근법은 어떻습니까 (C #)?

private int dividedBy3(int n) {
        List<Object> a = new Object[n].ToList();
        List<Object> b = new List<object>();
        while (a.Count > 2) {
            a.RemoveRange(0, 3);
            b.Add(new Object());
        }
        return b.Count;
    }

이 태그는 C 태그이고 첫날부터 그렇게되었습니다.
Lundin

4

정답은 다음과 같습니다.

기본 연산자를 사용하여 기본 작업을 수행하지 않는 이유는 무엇입니까?


그들이 알고 싶은 것은 프로세서가 내부적으로 어떻게 작동하는지 아는 것입니다 ... 수학 연산자를 사용하면 결국 위의 답변과 매우 유사한 작업을 수행합니다.
RaptorX

또는 그들은 당신이 쓸모없는 문제를 인식 할 수 있는지 알고 싶어합니다.
Gregoire

1
@Gregoire 동의합니다. aboloultley는 그러한 구현을 할 필요가 없습니다. comercial life (Orcale)의 Bit는 쓸모없는 요구 사항을 피하는 것이 필요합니다. 그? ")
AlexWien

4

fma () 라이브러리 함수를 사용하는 솔루션 은 모든 양수에 작동합니다.

#include <stdio.h>
#include <math.h>

int main()
{
    int number = 8;//Any +ve no.
    int temp = 3, result = 0;
    while(temp <= number){
        temp = fma(temp, 1, 3); //fma(a, b, c) is a library function and returns (a*b) + c.
        result = fma(result, 1, 1);
    } 
    printf("\n\n%d divided by 3 = %d\n", number, result);
}

내 또 다른 대답을 참조하십시오 .


도서관의 좋은 사용. 왜 결과 ++를 직접 사용하지 않았습니까?
그린 고블린

사람들은 +가 사용되었다고 말할 수 있습니다.
8

3

OS X의 Accelerate 프레임 워크의 일부로 포함 된 cblas를 사용하십시오 .

[02:31:59] [william@relativity ~]$ cat div3.c
#import <stdio.h>
#import <Accelerate/Accelerate.h>

int main() {
    float multiplicand = 123456.0;
    float multiplier = 0.333333;
    printf("%f * %f == ", multiplicand, multiplier);
    cblas_sscal(1, multiplier, &multiplicand, 1);
    printf("%f\n", multiplicand);
}

[02:32:07] [william@relativity ~]$ clang div3.c -framework Accelerate -o div3 && ./div3
123456.000000 * 0.333333 == 41151.957031

글쎄, 그것은 구현 세부 사항 일 뿐이므로 0.333333 대신 3.0 / 1.0으로 입력 할 수 있지만 규칙을 따라야합니다. 결정된!
wjl

원래 3.0 / 1.0으로 테스트를 수행했습니다. 더 높은 정밀도 숫자를 사용하면 상당히 정확한 결과를 얻을 수 있습니다. gist.github.com/3401496
wjl

3

일반적으로 이에 대한 해결책은 다음과 같습니다.

log(pow(exp(numerator),pow(denominator,-1)))


3

먼저:

x/3 = (x/4) / (1-1/4)

그런 다음 x / (1-y)를 해결하는 방법을 찾으십시오.

x/(1-1/y)
  = x * (1+y) / (1-y^2)
  = x * (1+y) * (1+y^2) / (1-y^4)
  = ...
  = x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i)) / (1-y^(2^(i+i))
  = x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i))

y = 1/4 인 경우 :

int div3(int x) {
    x <<= 6;    // need more precise
    x += x>>2;  // x = x * (1+(1/2)^2)
    x += x>>4;  // x = x * (1+(1/2)^4)
    x += x>>8;  // x = x * (1+(1/2)^8)
    x += x>>16; // x = x * (1+(1/2)^16)
    return (x+1)>>8; // as (1-(1/2)^32) very near 1,
                     // we plus 1 instead of div (1-(1/2)^32)
}

비록을 사용 +하지만 누군가가 이미 비트 단위 연산으로 add를 구현합니다.

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