source

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

factcode 2022. 8. 21. 14:07
반응형

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

3에 의해 사용하지를 사용하지 않고 않고 숫자를 3으로 나누려면어떻게 해야 합니까 많은 나눌 것이라고?*,/,+,-,%, 이동 통신사는?, 연산자?

번호는 서명 또는 서명되지 않을 수 있습니다.

이것은 원하는 작업을 수행하는 간단한 기능입니다.단, 필요한 것은+교환, 그렇게만 하면 남은 bit-operators로 값을 추가할 있다.연산자, 이제 비트맵을 사용하여 값을 추가하기만 하면 됩니다.

// 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, 즉, 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 위의 예에서는).바이트(예에서는 123456의 숫자 위의).
  2. rewind파일 포인터를 파일 앞쪽으로 리셋합니다.
  3. fread " " " 를 읽습니다.number「불필요」한 것은,divisor파일의 길이와 읽은 요소의 수를 반환합니다.

30바이트를 쓴 후 3단위로 파일을 다시 읽으면 10개의 "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;
}

기본 3 문자열로 변환하려면 itoa를 사용합니다.마지막 삼중수소를 떨어뜨리고 베이스 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
}

첫 번째:

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

「」를 사용하고 만,+, bitwiseop.d, add by bitwise op.d, add by bitwise op.d를 하고 있습니다

(플랫폼에 의존한) 인라인 어셈블리를 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;
}

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

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

을 작성하고 Pascal을 합니다.DIV환입니니다다

질문에는 c 가 붙어 있기 때문에 Pascal로 함수를 작성하여 C 프로그램에서 호출할 수 있습니다.그 방법은 시스템에 따라 다릅니다.

프리 파스칼을 하는 예가 .fp-compiler패키지가 인스톨 되어 있습니다.(전 순전히 잘못된 고집 때문에 이 일을 하는 것입니다.이것이 도움이 된다고는 생각하지 않습니다.)

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

정말 쉬워요.

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;

(물론 간결하게 하기 위해 일부 프로그램을 생략했습니다.)만약 프로그래머가 이 모든 것을 타이핑하는 것에 싫증이 난다면, 나는 프로그래머가 그를 위해 그것을 생성하기 위해 별도의 프로그램을 만들 수 있다고 확신한다. 어떤 것을 알게 되었습니다./그렇게 되면 그의 일이 엄청나게 간단해질 거야

(주의: 더 나은 버전은 아래 편집 2를 참조하십시오.)

[..] [..] [ ] [ ] [ ] [ ] using 、 [ ] using 、 [ ] using .. 롭 롭 롭 롭 롭 롭 롭 롭 롭 롭 롭 롭 롭롭 " 、 " 롭 롭 롭 " " 、 " " " " " " " " " " " " " " " " " "+[..] 연산자.를 사용하는 것을 금지하려면 , 다음을 참조해 주세요.+을 사용하다

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: 2를 : "Edit 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[] is is is is is is 와 같다type* const.

FWIW 를 하는 것과 수 .0x55555556안드레이가 제안한 트릭T:

int mul(int const x, int const y) {
  return sizeof(struct {
    char const ignore[y];
  }[x]);
}
int div3(int x)
{
  int reminder = abs(x);
  int result = 0;
  while(reminder >= 3)
  {
     result++;

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

카운터를 사용하는 것은 기본적인 해결책입니다.

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

계수 함수를 실행하는 것도 간단합니다. 코멘트를 확인하십시오.

모든 답변이 인터뷰 진행자가 듣기 좋아하는 내용은 아닐 수 있습니다.

답변:

"그런 바보 같은 짓에 누가 돈을 내겠어요.아무도 그것에 대해 유리하지 않을 것이다. 그것은 빠르지도 않고, 단지 바보같을 뿐이다.Prozessor 설계자는 이 점을 알아야 합니다.단, 이는 3인치로 나눗셈하는 것뿐만 아니라 모든 숫자에 유효해야 합니다.

또 다른 해결책입니다.하드 코드 예외로 처리해야 하는 int의 최소값을 제외한 모든 int(음수 int 포함)를 처리해야 합니다.이것은 기본적으로 뺄셈으로 나누지만 비트 연산자(Shift, xor 및 complete)만 사용합니다.더 빠른 속도를 위해 3 * (2의 거듭제곱 감소)를 뺍니다.c# 에서는, 이러한 DivideBy3 콜의 약 444개/밀리초(1,000,000 dives의 경우는 2.2초)가 실행되기 때문에, 매우 느리지는 않습니다만, 단순한 x/3 에 가까운 속도에서는 실행할 수 없습니다.이에 비해 쿠디의 멋진 솔루션은 이보다 약 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와의 차이는 경미할 것입니다.

/오퍼레이터 behinds'는 'behind the behinds'를 사용하여 조작합니다.eval트링연??? ??

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

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

내가 생각해낸 것 중 첫 번째.

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스트링 포맷에 대한 아이디어도 쓸 수 있을 것 같아요.

이 어프로치(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;
    }

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

내 다른 답을 봐.

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

좋아, 우리 모두 이게 현실세계의 문제가 아니라는 것에 동의한다고 생각해.재미삼아 Ada와 멀티스레딩을 사용하는 방법은 다음과 같습니다.

with Ada.Text_IO;

procedure Divide_By_3 is

   protected type Divisor_Type is
      entry Poke;
      entry Finish;
   private
      entry Release;
      entry Stop_Emptying;
      Emptying : Boolean := False;
   end Divisor_Type;

   protected type Collector_Type is
      entry Poke;
      entry Finish;
   private
      Emptying : Boolean := False;
   end Collector_Type;

   task type Input is
   end Input;
   task type Output is
   end Output;

   protected body Divisor_Type is
      entry Poke when not Emptying and Stop_Emptying'Count = 0 is
      begin
         requeue Release;
      end Poke;
      entry Release when Release'Count >= 3 or Emptying is
         New_Output : access Output;
      begin
         if not Emptying then
            New_Output := new Output;
            Emptying := True;
            requeue Stop_Emptying;
         end if;
      end Release;
      entry Stop_Emptying when Release'Count = 0 is
      begin
         Emptying := False;
      end Stop_Emptying;
      entry Finish when Poke'Count = 0 and Release'Count < 3 is
      begin
         Emptying := True;
         requeue Stop_Emptying;
      end Finish;
   end Divisor_Type;

   protected body Collector_Type is
      entry Poke when Emptying is
      begin
         null;
      end Poke;
      entry Finish when True is
      begin
         Ada.Text_IO.Put_Line (Poke'Count'Img);
         Emptying := True;
      end Finish;
   end Collector_Type;

   Collector : Collector_Type;
   Divisor : Divisor_Type;

   task body Input is
   begin
      Divisor.Poke;
   end Input;

   task body Output is
   begin
      Collector.Poke;
   end Output;

   Cur_Input : access Input;

   -- Input value:
   Number : Integer := 18;
begin
   for I in 1 .. Number loop
      Cur_Input := new Input;
   end loop;
   Divisor.Finish;
   Collector.Finish;
end Divide_By_3;
#!/bin/ruby

def div_by_3(i)
  i.div 3        # always return int http://www.ruby-doc.org/core-1.9.3/Numeric.html#method-i-div
end

2진수로 표시되는 3의 나눗셈 기준은 아무도 언급하지 않은 것 같습니다. 짝수 자리의 합은 홀수 자릿수의 합과 같아야 합니다(10진수 기준 11과 유사).Check a number is dividable 3(숫자가 3으로 나누어지는지 확인) 아래에 이 방법을 사용하는 솔루션이 있습니다.

나는 이것이 Michael Burr의 편집자가 언급한 가능한 복제품이라고 생각한다.

이것은 Python에서 문자열 비교와 스테이트 머신을 사용한 것입니다.

def divide_by_3(input):
  to_do = {}
  enque_index = 0
  zero_to_9 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  leave_over = 0
  for left_over in (0, 1, 2):
    for digit in zero_to_9:
      # left_over, digit => enque, leave_over
      to_do[(left_over, digit)] = (zero_to_9[enque_index], leave_over)
      if leave_over == 0:
        leave_over = 1
      elif leave_over == 1:
        leave_over = 2
      elif leave_over == 2 and enque_index != 9:
        leave_over = 0
        enque_index = (1, 2, 3, 4, 5, 6, 7, 8, 9)[enque_index]
  answer_q = []
  left_over = 0
  digits = list(str(input))
  if digits[0] == "-":
    answer_q.append("-")
  digits = digits[1:]
  for digit in digits:
    enque, left_over = to_do[(left_over, int(digit))]
    if enque or len(answer_q):
      answer_q.append(enque)
  answer = 0
  if len(answer_q):
    answer = int("".join([str(a) for a in answer_q]))
  return answer

그래프나 트리와 같은 구조를 사용하여 문제를 해결할 수 있습니다.기본적으로 3으로 나누는 숫자와 같은 수의 정점을 생성합니다.그런 다음 쌍으로 구성되지 않은 각 정점을 다른 두 정점과 계속 쌍으로 구성합니다.

대략적인 의사 코드:

function divide(int num)
    while(num!=0)
        Add a new vertice to vertiexList.
        num--
    quotient = 0
    for each in vertexList(lets call this vertex A)
        if vertexList not empty
            Add an edge between A and another vertex(say B)
        else
            your Remainder is 1 and Quotient is quotient
        if vertexList not empty
            Add an edge between A and another vertex(say C)
        else
            your remainder is 2 and Quotient is quotient
        quotient++
        remove A, B, C from vertexList
    Remainder is 0 and Quotient is quotient

이것은 분명히 최적화할 수 있고 복잡도는 숫자의 크기에 따라 다르지만 ++와 --를 실행할 수 있다면 효과가 있을 것입니다.쿨러만 세는 거나 마찬가지야.

여기 제가 어렸을 때 할아버지가 가르쳐 주신 방법이 있습니다.+ 및 / 연산자가 필요하지만 계산이 쉬워집니다.

개별 숫자를 합산하여 3의 배수인지 확인합니다.

그러나 이 방법은 12보다 큰 숫자에 적용됩니다.

예: 36,

3+6=9는 3의 배수입니다.

42,

4+2=6은 3의 배수이다.

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

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

이제 a의 비트 시프트 값을 더하기만 하면 됩니다.어머!하지만 추가할 수 없기 때문에 대신 비트 연산자를 사용하여 추가 함수를 작성해야 합니다.비트 연산자에 대해 잘 알고 계시다면, 제 솔루션은 상당히 단순해 보일 것입니다.혹시 모르니까 마지막에 예를 들어볼게요

또 한 가지 주의할 점은 먼저 왼쪽으로 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

의 응답을 가정합니다.div_by_3(a)x, 그 다음 = x, 그럼x <= floor(f(a, i)) < a / 3★★★★★★★★★★★★★★★★★.a = 3k틀린 답을 얻습니다.

좋습니다.

$ num=1337; printf "scale=5;${num}\x2F3;\n" | bc
445.66666

세툰 컴퓨터에서는 쉽게 가능합니다.

정수를 3으로 나누려면 오른쪽으로 1자리씩 이동합니다.

그러나 이러한 플랫폼에 적합한 C 컴파일러를 구현하는 것이 엄밀하게 가능한지는 잘 모르겠습니다.예를 들어 "최소 8비트"를 "-128에서 +127까지의 정수를 유지할 수 있다"로 해석하는 등 규칙을 약간 확장해야 할 수 있습니다.

이 조작은 유효합니다.

smegma$ curl http://www.wolframalpha.com/input/?i=14+divided+by+3 2>/dev/null | gawk 'match($0, /link to /input/\?i=([0-9.+-]+)/, ary) { print substr( $0, ary[1, "start"], ary[1, "length"] )}' 4.6666666666666666666666666666666666666666666666666666

14와 3을 숫자로 대체하세요.

언급URL : https://stackoverflow.com/questions/11694546/divide-a-number-by-3-without-using-operators

반응형