*
、/
、+
、-
、%
のような演算子を使わずに、数値を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
、そしてiterate
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)
の結果を追加してください。
仕組みの説明
fwrite
はnumber
バイトを書き込みます(上記の例では123456です)。rewind
は、ファイルポインタをファイルの先頭にリセットします。fread
は、ファイルからnumber
の長さの最大divisor
"records"を読み込み、読み込んだ要素数を返します。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 を削除して基数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を参照してください!)
「[..] +
[..]operatorsを使用せずに」と言ったので、これは思ったほどトリッキーではありません。 +
文字を一緒に使用することを禁止する場合は、以下を参照してください。
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)
}
+
、-
、*
、/
、%
charactersを含む演算子を使用しないわずかに高速なバージョン。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;
}
構文*
がtype[]
と同一である関数パラメーターリストを除き、type* const
文字を使用せずにポインターのタイプを示すことができないため、add
関数の最初の引数を使用します。
FWIW、あなたは AndreyT によって提案された0x55555556
トリックを使用するために同様のトリックを使用して乗算関数を簡単に実装できます:
int mul(int const x, int const y) {
return sizeof(struct {
char const ignore[y];
}[x]);
}
Setunコンピューター で簡単に可能です。
整数を3で除算するには、 1桁右にシフトします 。
そのようなプラットフォーム上で準拠Cコンパイラを実装することが厳密に可能かどうかはわかりません。 「少なくとも8ビット」を「少なくとも-128から+127までの整数を保持できる」と解釈するなど、規則を少し拡張する必要があるかもしれません。
Oracleからのものなので、事前に計算された回答のルックアップテーブルはどうでしょうか。 :-D
これが私の解決策です:
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 <= floor(f(a, i)) < a / 3
の結果を仮定します。 a = 3k
のとき、私たちは間違った答えを得ます。
32ビットの数を3で割るには、それに0x55555556
を掛けてから、64ビットの結果の上位32ビットを取ります。
あとは、ビット演算とシフトを使って乗算を実装するだけです。
さらに別の解決策これは、intの最小値を除くすべての整数(負の整数を含む)を処理する必要があります。これは、ハードコードされた例外として処理する必要があります。これは基本的に減算による除算を行いますが、ビット演算子(シフト、xor、&、および補数)のみを使用します。より速いスピードのために、それは3 *を引きます(2のべき乗を減らす)。 c#では、1ミリ秒あたり約444回のDivideBy3呼び出し(1,000,000回の除算で2.2秒)を実行するので、それほど恐ろしいほど遅くはありませんが、単純なx/3ほど速くはありません。比較すると、CoodeyのNiceソリューションは、これより約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との違いは小さいはずです。
とても簡単です。
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;
プログラマーがこれをすべてタイプするのに飽きたら、彼または彼女は彼のためにそれを生成するために別のプログラムを書くことができると確信しています。偶然にも、特定の演算子/
を知っていると、それは彼の仕事を非常に単純化するでしょう。
カウンタを使用するのが基本的な解決策です。
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
}
}
モジュラス関数を実行することも簡単です。コメントを確認してください。
これは基数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);
}
プログラムをPascalで作成し、DIV
演算子を使用してください。
質問には c というタグが付いているので、おそらくPascalで関数を書いて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
int div3(int x)
{
int reminder = abs(x);
int result = 0;
while(reminder >= 3)
{
result++;
reminder--;
reminder--;
reminder--;
}
return result;
}
この答えがすでに公開されているかどうかをクロスチェックしませんでした。プログラムを浮動小数点数に拡張する必要がある場合は、その数字に必要な精度の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;
}
これは3つだけでなく、どの除数でもうまくいくはずです。現在はunsignedのみですが、それをsignedに拡張するのはそれほど難しくありません。
#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;
}
eval
と文字列の連結を使用して「裏で」/
演算子を使用するのは不正ですか?
たとえば、Javaスクリプトでは、次のことができます。
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プログラムを生成します。
#!/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));
}
''')
int divideByThree(int num)
{
return (fma(num, 1431655766, 0) >> 32);
}
fma は、math.h
ヘッダーに定義されている標準ライブラリ関数です。
私は正しい答えだと思います。
基本演算を実行するために基本演算子を使用しないのはなぜですか?
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);
}
このアプローチはどうですか(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;
}
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
最初:
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を実行します
すべての答えは、インタビュアーが聞いたことが好きだったというわけではないでしょう。
私の答え:
「そのようなばかげたことにお金を払う人はいないだろう。誰もがそれに有利になるわけではない、それほど速くない、そのばかげたことだけではない。 3 "による除算
さて、私たち全員がこれが現実の問題ではないことに同意すると思います。それで、楽しみのためだけに、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;
まったく一般的な区分で答えられた人はいませんでした。
/* 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;
}
ビットごとの加算はすでに答えの1つで与えられているので、それをスキップします。
一般的に、これに対する解決策は以下のようになります。
log(pow(exp(numerator),pow(denominator,-1)))
大学で学んだ定義をそのまま適用しないのはなぜですか。乗算は単なる再帰的減算であり、減算は加算であるので、結果は非効率的ではあるが明らかであり、その場合、加算は再帰的なxおよび/および論理ポートの組み合わせによって実行できる。
#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;
}
誰かが言うように...最初にこの作品を作ります。アルゴリズムは負のQに対しても機能するはずです。
#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;
}
標準の学校分割方法を思い出して2進法で行うと、3の場合は限られた値のセット(この場合は0から5)だけを分割および減算することに気付くでしょう。これらは算術演算子を取り除くためにswitch文で扱うことができます。
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);
}
InputValueは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
これは動作します...
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」をあなたの数字に置き換えてください。
基数2の3は11です。
ですから、(中学校のように)長い除算をベース2で11にするだけです。ベース2では、ベース10よりもさらに簡単です。
最上位から始まる各ビット位置に対して、
接頭辞が11より小さいかどうかを決定します。
0が出力されている場合.
1が出力されない場合は、適切な変更のためにプレフィックスビットを代入します。ケースは3つしかありません。
11xxx -> xxx (ie 3 - 3 = 0)
100xxx -> 1xxx (ie 4 - 3 = 1)
101xxx -> 10xxx (ie 5 - 3 = 2)
他のすべての接頭辞は到達不能です。
最下位ビット位置まで繰り返すと完了です。
このコードを使用して、すべての正の非浮動小数点数を除算します。基本的には、被除数ビットと一致するように除数ビットを左に揃えます。被除数の各セグメント(除数のサイズ)について、被除数のセグメントが除数より大きいかどうかを確認したい場合は、左にシフトしてから最初のレジストラのORにします。この概念は、もともと2004年に作成されたものです(私は信じています)。これは、その概念を使用したCバージョンです。注:(私はそれを少し修正しました)
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)
}
使用例
int n = divide( 3, 6); //outputs 2
__div__
が正字表記ではないと考えた場合/
def divBy3(n):
return n.__div__(3)
print divBy3(9), 'or', 9//3
偶数桁の合計が奇数桁の合計と等しいはずです(10進数の11の基準に似ている)。 の下にこのトリックを使用した解決策があります。番号が3で割り切れるかどうかを確認します 。
私はこれがMichael Burrの編集が述べた可能性のある複製であると思う。
#!/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