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

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

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



답변

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

// 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


답변

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

#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


답변

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


답변

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


답변

예를 들어 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;
}


답변

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
}


답변

(참고 : 더 나은 버전을 보려면 아래 편집 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]);
}