web-dev-qa-db-fra.com

Diviser un nombre par 3 sans utiliser d'opérateurs *, /, +, -,%

Comment diviseriez-vous un nombre par 3 sans utiliser les opérateurs *, /, +, -, %?

Le numéro peut être signé ou non signé.

674
Green goblin

Ceci est un fonction simple qui effectue l'opération souhaitée. Mais cela nécessite l'opérateur +, il ne vous reste donc qu'à ajouter les valeurs avec des opérateurs de bits:

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

Comme Jim a commenté cela fonctionne, parce que:

  • n = 4 * a + b
  • n / 3 = a + (a + b) / 3
  • Donc, sum += a, n = a + b, et itérer

  • Lorsque a == 0 (n < 4), sum += floor(n / 3);, c'est-à-dire 1, if n == 3, else 0

542
qwertz

Les conditions idiotes appellent une solution idiote:

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

Si la partie décimale est également nécessaire, déclarez simplement result comme double et ajoutez-y le résultat de fmod(number,divisor).

Explication du fonctionnement

  1. La fwrite écrit number octets (le nombre étant 123456 dans l'exemple ci-dessus).
  2. rewind réinitialise le pointeur de fichier à l'avant du fichier.
  3. fread lit un maximum de number "enregistrements" d'une longueur de divisor à partir du fichier et renvoie le nombre d'éléments lus.

Si vous écrivez 30 octets puis relisez le fichier par unités de 3, vous obtenez 10 "unités". 30/3 = 10

434
Matteo Italia
log(pow(exp(number),0.33333333333333333333)) /* :-) */
306
Alan Curry
#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;
}
204
nos

Vous pouvez utiliser un assemblage en ligne (dépendant de la plate-forme), par exemple pour x86: (fonctionne également pour les nombres négatifs)

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

Utilisez itoa pour convertir en chaîne de base 3. Supprimez le dernier trit et reconvertissez-le en 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
}
105
Bo Lu

(note: voir Edit 2 ci-dessous pour une meilleure version!)

Ce n’est pas aussi compliqué que cela en a l'air, car vous avez dit "sans utiliser les opérateurs [..] + [..] ". Voir ci-dessous, si vous souhaitez interdire l’utilisation simultanée du caractère +.

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

puis il suffit de dire div_by(100,3) pour diviser 100 par 3.


Edit : Vous pouvez également remplacer l'opérateur ++:

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

Edit 2: Version légèrement plus rapide sans utiliser d'opérateur contenant les caractères +, -, *, /, %.

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

Nous utilisons le premier argument de la fonction add car nous ne pouvons pas désigner le type de pointeurs sans utiliser le caractère *, sauf dans les listes de paramètres de fonction, où la syntaxe type[] est identique à type* const.

FWIW, vous pouvez facilement implémenter une fonction de multiplication en utilisant une astuce similaire pour utiliser l’astuce 0x55555556 proposée par AndreyT :

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

C'est facilement possible sur le ordinateur Setun .

Pour diviser un entier par 3, décalage droit de 1 place .

Je ne sais pas s'il est strictement possible d'implémenter un compilateur C conforme sur une telle plate-forme. Nous devrons peut-être étirer un peu les règles, comme interpréter "au moins 8 bits" comme "capable de contenir au moins des entiers de -128 à +127".

45
Mechanical snail

Depuis Oracle, qu’en est-il d’une table de recherche de réponses pré-calculées? :-RÉ

33
Jeff Martin

Voici ma solution:

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

Tout d'abord, notez que

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

Maintenant, le reste est simple!

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

Il ne reste plus qu’à additionner ces valeurs décalées un! Oops! Cependant, nous ne pouvons pas ajouter, alors nous devrons écrire une fonction add en utilisant des opérateurs binaires! Si vous connaissez les opérateurs au niveau des bits, ma solution devrait paraître assez simple ... mais juste au cas où vous ne l'êtes pas, je vais vous donner un exemple à la fin.

Une autre chose à noter est que je décale d’abord de 30 à gauche! Cela permet de s’assurer que les fractions ne sont pas arrondies.

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!

C'est simplement un ajout que vous avez appris en tant qu'enfant!

111
 1011
+0110
-----
10001

Cette implémentation échec car nous ne pouvons pas ajouter tous les termes de l'équation:

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

Supposons le résultat de div_by_3(a) = x, puis x <= floor(f(a, i)) < a / 3. Quand a = 3k, nous obtenons une mauvaise réponse.

32
tschultz

Pour diviser un nombre de 32 bits par 3, on peut le multiplier par 0x55555556, puis prendre les 32 bits supérieurs du résultat 64 bits.

Il ne reste plus maintenant qu'à implémenter la multiplication à l'aide d'opérations et de décalages de bits ...

25
AnT

Encore une autre solution. Cela devrait gérer toutes les entrées (y compris les entrées négatives) à l'exception de la valeur minimale d'un int, qui devrait être traitée comme une exception codée en dur. Cela consiste essentiellement en une division par soustraction, mais en utilisant uniquement des opérateurs de bits (décalages, xor et & complément). Pour une vitesse plus rapide, il soustrait 3 * (puissance décroissante de 2). En c #, il exécute environ 444 de ces appels DivideBy3 par milliseconde (2,2 secondes pour 1 000 000 de divisions), ce qui signifie qu’il n’est pas extrêmement lent, mais pas aussi rapide qu’un simple x/3. En comparaison, la solution Nice de Coodey est environ 5 fois plus rapide que celle-ci.

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'est c # parce que c'est ce que j'avais à portée de main, mais les différences avec c devraient être mineures.

18
hatchet

C'est vraiment très facile.

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;

(J'ai bien sûr omis une partie du programme pour des raisons de brièveté.) Si le programmeur en a assez de taper tout cela, je suis sûr qu'il ou elle pourra écrire un programme séparé pour le générer. Je suis au courant d’un certain opérateur, /, qui simplifierait énormément son travail.

15
thedayturns

L'utilisation de compteurs est une solution de base:

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

Il est également facile d'effectuer une fonction de module, vérifiez les commentaires.

14
GJ.

Celui-ci est l'algorithme de division classique en base 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);
}
11
Eric Bainville

Ecrivez le programme en Pascal et utilisez l'opérateur DIV.

Puisque la question est étiquetée c , vous pouvez probablement écrire une fonction en Pascal et l'appeler à partir de votre programme C; la méthode pour le faire est spécifique au système.

Mais voici un exemple qui fonctionne sur mon système Ubuntu avec le paquet Free Pascal _fp-compiler_ installé. (Je le fais par pure obstination; je ne prétends pas que cela est utile.)

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

Pour construire:

_fpc divide_by_3.pas && gcc divide_by_3.o main.c -o main
_

Exemple d'exécution:

_$ ./main
Enter a number: 100
100 / 3 = 33
_
9
Keith Thompson
int div3(int x)
{
  int reminder = abs(x);
  int result = 0;
  while(reminder >= 3)
  {
     result++;

     reminder--;
     reminder--;
     reminder--;
  }
  return result;
}
8
Amir Saniyan

N'a pas vérifié si cette réponse est déjà publiée. Si le programme doit être étendu aux nombres flottants, les nombres peuvent être multipliés par 10 * nombre de précision nécessaire, puis le code suivant peut être appliqué à nouveau.

#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
PermanentGuest

Utilisation de Mathématiques BC dans PHP :

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

MySQL (c'est une interview d'Oracle)

> SELECT 12345 DIV 3;

Pascal :

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

x86-64 Langue d'assemblage:

mov  r8, 3
xor  rdx, rdx   
mov  rax, 12345
idiv r8
7
Pedro L.

Cela devrait fonctionner pour tout diviseur, pas seulement trois. Actuellement, uniquement pour les non-signés, mais l’extension à signée ne devrait pas être aussi difficile.

#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
wildplasser

Serait-il trompeur d'utiliser l'opérateur / "dans les coulisses" en utilisant eval et la concaténation de chaînes?

Par exemple, dans Javacript, vous pouvez faire

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

D'abord que je suis venu avec.

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

EDIT: Désolé, je n'ai pas remarqué le tag C. Mais vous pouvez utiliser l’idée du formatage des chaînes, je suppose ...

6
defhlt

Le script suivant génère un programme C qui résout le problème sans utiliser les opérateurs * / + - %:

#!/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));
}
''')
5
Mechanical snail

Utiliser Calculateur de nombres de Hacker's Delight Magic

int divideByThree(int num)
{
  return (fma(num, 1431655766, 0) >> 32);
}

fma est une fonction de bibliothèque standard définie dans l'en-tête math.h.

5
Jainendra

Je pense que la bonne réponse est:

Pourquoi n'utiliserais-je pas un opérateur de base pour effectuer une opération de base?

4
Gregoire

Solution utilisant fonction de bibliothèque fma () , fonctionne pour tout nombre positif:

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

Voir ma autre réponse .

4
Eight

Comment sur cette approche (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;
    }
4
mclafee

Utilisez cblas , inclus dans la structure Accelerate d’OS X.

[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
3
wjl

Première:

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

Puis trouvez comment résoudre 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))

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

Bien qu'il utilise +, mais quelqu'un implémente déjà add by bitwise op.

3
Zang MingJie

Toutes les réponses ne sont probablement pas ce que l'intervieweur a aimé entendre:

Ma réponse:

"Je ne ferais jamais cela, qui me paierait pour des choses aussi stupides. Personne n'y aura d'avantage, ce n'est pas plus rapide, c'est seulement bête. Les concepteurs de Prozessor doivent le savoir, mais cela doit alors fonctionner pour tous les chiffres, pas seulement pour division par 3 "

2
AlexWien

D'accord, je pense que nous sommes tous d'accord pour dire que ce n'est pas un problème du monde réel. Donc, juste pour le plaisir, voici comment faire avec Ada et le multithreading:

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;
2
flyx

Très amusé, aucune réponse avec une division générique:

/* For the given integer find the position of MSB */
int find_msb_loc(unsigned int n)
{
    if (n == 0)
        return 0;

    int loc = sizeof(n)  * 8 - 1;
    while (!(n & (1 << loc)))
        loc--;
    return loc;
}


/* Assume both a and b to be positive, return a/b */
int divide_bitwise(const unsigned int a, const unsigned int b)
{
    int int_size = sizeof(unsigned int) * 8;
    int b_msb_loc = find_msb_loc(b);

    int d = 0; // dividend
    int r = 0; // reminder
    int t_a = a;
    int t_a_msb_loc = find_msb_loc(t_a);
    int t_b = b << (t_a_msb_loc - b_msb_loc);

    int i;
    for(i = t_a_msb_loc; i >= b_msb_loc; i--)  {
        if (t_a > t_b) {
            d = (d << 1) | 0x1;
            t_a -= t_b; // Not a bitwise operatiion
            t_b = t_b >> 1;
         }
        else if (t_a == t_b) {
            d = (d << 1) | 0x1;
            t_a = 0;
        }
        else { // t_a < t_b
            d = d << 1;
            t_b = t_b >> 1;
        }
    }

    r = t_a;
    printf("==> %d %d\n", d, r);
    return d;
}

L'addition au niveau des bits a déjà été donnée dans l'une des réponses, donc sautez-la.

2
Xolve

En règle générale, une solution à ce problème serait:

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

1
Gaurav Narang

Pourquoi n'appliquons-nous pas simplement la définition étudiée au collège? Le résultat peut être inefficace mais clair, car la multiplication est simplement une soustraction récursive et la soustraction est une addition, puis l'addition peut être effectuée par une combinaison récursive xor/et de ports logiques.

#include <stdio.h>

int add(int a, int b){
   int rc;
   int carry;
   rc = a ^ b; 
   carry = (a & b) << 1;
   if (rc & carry) 
      return add(rc, carry);
   else
      return rc ^ carry; 
}

int sub(int a, int b){
   return add(a, add(~b, 1)); 
}

int div( int D, int Q )
{
/* lets do only positive and then
 * add the sign at the end
 * inversion needs to be performed only for +Q/-D or -Q/+D
 */
   int result=0;
   int sign=0;
   if( D < 0 ) {
      D=sub(0,D);
      if( Q<0 )
         Q=sub(0,Q);
      else
         sign=1;
   } else {
      if( Q<0 ) {
         Q=sub(0,Q);
         sign=1;
      } 
   }
   while(D>=Q) {
      D = sub( D, Q );
      result++;
   }
/*
* Apply sign
*/
   if( sign )
      result = sub(0,result);
   return result;
}

int main( int argc, char ** argv ) 
{
    printf( "2 plus 3=%d\n", add(2,3) );
    printf( "22 div 3=%d\n", div(22,3) );
    printf( "-22 div 3=%d\n", div(-22,3) );
    printf( "-22 div -3=%d\n", div(-22,-3) );
    printf( "22 div 03=%d\n", div(22,-3) );
    return 0;
}

Comme le dit quelqu'un ... faites d'abord ce travail. Notez que cet algorithme devrait fonctionner pour Q négatif ...

1
Jekyll
#include <stdio.h>

typedef struct { char a,b,c; } Triple;

unsigned long div3(Triple *v, char *r) {
  if ((long)v <= 2)  
    return (unsigned long)r;
  return div3(&v[-1], &r[1]);
}

int main() {
  unsigned long v = 21; 
  int r = div3((Triple*)v, 0); 
  printf("%ld / 3 = %d\n", v, r); 
  return 0;
}
1
perreal

Si vous vous rappelez la méthode de division standard de l'école et que vous le faites en binaire, vous découvrirez que dans le cas de 3, vous ne divisez et ne soustrayez qu'un ensemble limité de valeurs (de 0 à 5 dans ce cas). Ceux-ci peuvent être traités avec une instruction switch pour se débarrasser des opérateurs arithmétiques.

static unsigned lamediv3(unsigned n)
{
  unsigned result = 0, remainder = 0, mask = 0x80000000;

  // Go through all bits of n from MSB to LSB.
  for (int i = 0; i < 32; i++, mask >>= 1)
  {
    result <<= 1;
    // Shift in the next bit of n into remainder.
    remainder = remainder << 1 | !!(n & mask);

    // Divide remainder by 3, update result and remainer.
    // If remainder is less than 3, it remains intact.
    switch (remainder)
    {
    case 3:
      result |= 1;
      remainder = 0;
      break;

    case 4:
      result |= 1;
      remainder = 1;
      break;

    case 5:
      result |= 1;
      remainder = 2;
      break;
    }
  }

  return result;
}

#include <cstdio>

int main()
{
  // Verify for all possible values of a 32-bit unsigned integer.
  unsigned i = 0;

  do
  {
    unsigned d = lamediv3(i);

    if (i / 3 != d)
    {
      printf("failed for %u: %u != %u\n", i, d, i / 3);
      return 1;
    }
  }
  while (++i != 0);
}
1
kyku

InputValue est le nombre à diviser par 3

SELECT AVG(NUM) 
  FROM (SELECT InputValue NUM from sys.dual
         UNION ALL SELECT 0 from sys.dual
         UNION ALL SELECT 0 from sys.dual) divby3
1
Craig

Cela fonctionnera:

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

Il suffit de remplacer "14" et "3" par vos chiffres.

0
CPRitter

3 en base 2 est 11.

Il suffit donc de faire une longue division (comme au collège) en base 2 par 11. C'est encore plus facile en base 2 qu'en base 10.

Pour chaque position de bit commençant par le plus significatif:

Décidez si le préfixe est inférieur à 11.

Si c'est la sortie 0.

S'il ne s'agit pas de la sortie 1, remplacez ensuite les bits de préfixe par la modification appropriée. Il n'y a que trois cas:

 11xxx ->    xxx    (ie 3 - 3 = 0)
100xxx ->   1xxx    (ie 4 - 3 = 1)
101xxx ->  10xxx    (ie 5 - 3 = 2)

Tous les autres préfixes sont inaccessibles.

Répétez jusqu'à la position la plus basse et vous avez terminé.

0
Andrew Tomazos

J'utiliserais ce code pour diviser tous les nombres positifs non flottants. En gros, vous souhaitez aligner les bits du diviseur à gauche pour les faire correspondre aux bits de dividende. Pour chaque segment du dividende (taille du diviseur) que vous souhaitez vérifier pour vous assurer que le segment du dividende est supérieur au diviseur, vous souhaitez alors déplacer à gauche puis OR dans le premier registraire. Ce concept a été créé en 2004 (standford je crois), voici une version C qui utilise ce concept. Note: (je l'ai modifié un peu)

int divide(int a, int b)
{
    int c = 0, r = 32, i = 32, p = a + 1;
    unsigned long int d = 0x80000000;

    while ((b & d) == 0)
    {
        d >>= 1;
        r--;
    }

    while (p > a)
    {
        c <<= 1;
        p = (b >> i--) & ((1 << r) - 1);
        if (p >= a)
            c |= 1;
    }
    return c; //p is remainder (for modulus)
}

Exemple d'utilisation:

int n = divide( 3, 6); //outputs 2
0
MysteryDev

si on considère __div__ n'est pas orthographiquement /

def divBy3(n):
    return n.__div__(3)

print divBy3(9), 'or', 9//3
0
user1125394

Il semble que personne n'ait mentionné le critère de division pour 3 représenté en binaire - la somme des chiffres pairs devrait être égale à la somme des chiffres impairs (similaire au critère de 11 en décimal). Il existe des solutions en utilisant cette astuce sous Vérifiez si un nombre est divisible par .

Je suppose que c'est le doublon possible mentionné par le montage de Michael Burr.

0
yoniLavi
#!/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
0
A B