_%
_、_/
_または_*
_を使用せずに、数値が3で割り切れるかどうかを調べる必要があります。与えられたヒントは、atoi()
関数を使用することでした。それを行う方法はありますか?
どちらかになるまで3を引く
a)ヒット0-数は3で割り切れる
b)0未満の数値を取得する-数値は割り切れなかった
-指摘された問題を修正するために編集されたバージョン
while n > 0:
n -= 3
while n < 0:
n += 3
return n == 0
「すべての桁を追加し、それが3で除算されるかどうかを確認する」を適用すると、現在のところ、10進数字にすべての焦点が当てられます。そのトリックは実際には16進数でも機能します。例えば0x1 + 0x2 = 0x3であるため、0x12は3で除算できます。また、16進数への「変換」は、10進数への変換よりもはるかに簡単です。
疑似コード:
int reduce(int i) {
if (i > 0x10)
return reduce((i >> 4) + (i & 0x0F)); // Reduces 0x102 to 0x12 to 0x3.
else
return i; // Done.
}
bool isDiv3(int i) {
i = reduce(i);
return i==0 || i==3 || i==6 || i==9 || i==0xC || i == 0xF;
}
[編集] Rに触発された、より高速なバージョン(OログログN):
int reduce(unsigned i) {
if (i >= 6)
return reduce((i >> 2) + (i & 0x03));
else
return i; // Done.
}
bool isDiv3(unsigned i) {
// Do a few big shifts first before recursing.
i = (i >> 16) + (i & 0xFFFF);
i = (i >> 8) + (i & 0xFF);
i = (i >> 4) + (i & 0xF);
// Because of additive overflow, it's possible that i > 0x10 here. No big deal.
i = reduce(i);
return i==0 || i==3;
}
数値を数字に分割します。数字を一緒に追加します。数字が1つだけになるまで繰り返します。その数字が3、6、または9の場合、数値は3で割り切れます(そして、特別な場合として0を処理することを忘れないでください)。
文字列に変換してから10進数を一緒に追加する手法は洗練されていますが、除算が必要になるか、文字列への変換手順では非効率的です。最初に10進数の文字列に変換せずに、アイデアを2進数に直接適用する方法はありますか?
結局、あります:
2進数の場合、奇数ビットの合計から偶数ビットの合計を引いた数は、元の数が3で割り切れる場合を除いて、3で割り切れる。
例として、3で割り切れる数値3726を取り上げます。バイナリでは、これは111010001110
。したがって、奇数の桁を、右から左に向かって[1、1、0、1、1、1]とします。これらの合計は5です。偶数ビットは[0、1、0、0、0、1]です。これらの合計は2です。 5-2 =3。これから、元の数は3で割り切れると結論付けることができます。
インタビューの質問では、本質的に、3を除数とする分割可能性ルールの省略形を考え出す(またはすでに知っている)ように求められます。
3の分割可能ルールの1つは次のとおりです。
任意の数を取り、数の各桁を加算します。次に、その合計を取り、それが3で割り切れるかどうかを判断します(必要に応じて同じ手順を繰り返します)。最後の数が3で割り切れる場合、元の数は3で割り切れる。
例:
16,499,205,854,376
=> 1+6+4+9+9+2+0+5+8+5+4+3+7+6 sums to 69
=> 6 + 9 = 15 => 1 + 5 = 6, which is clearly divisible by 3.
3で割り切れる数iircには、その桁の合計が3で割り切れるという特性があります。たとえば、
12 -> 1 + 2 = 3
144 -> 1 + 4 + 4 = 9
Javaの私の解決策は32ビットでのみ機能しますnsignedint
s。
static boolean isDivisibleBy3(int n) {
int x = n;
x = (x >>> 16) + (x & 0xffff); // max 0x0001fffe
x = (x >>> 8) + (x & 0x00ff); // max 0x02fd
x = (x >>> 4) + (x & 0x000f); // max 0x003d (for 0x02ef)
x = (x >>> 4) + (x & 0x000f); // max 0x0011 (for 0x002f)
return ((011111111111 >> x) & 1) != 0;
}
最初に、数を32未満の数に減らします。最後の手順では、マスクを適切な回数だけ右にシフトすることにより、可分性をチェックします。
与えられた数x。 xを文字列に変換します。文字列を文字ごとに解析します。解析された各文字を(atoi()を使用して)数値に変換し、これらすべての数値を新しい数値yに加算します。最終的に得られる数値が1桁になるまで、このプロセスを繰り返します。その1桁が3、6、または9の場合、元の数xは3で割り切れます。
あなたはこのCにタグを付けませんでしたが、atoi
について言及したので、Cのソリューションを提供します。
int isdiv3(int x)
{
div_t d = div(x, 3);
return !d.rem;
}
bool isDiv3(unsigned int n)
{
unsigned int n_div_3 =
n * (unsigned int) 0xaaaaaaab;
return (n_div_3 < 0x55555556);//<=>n_div_3 <= 0x55555555
/*
because 3 * 0xaaaaaaab == 0x200000001 and
(uint32_t) 0x200000001 == 1
*/
}
bool isDiv5(unsigned int n)
{
unsigned int n_div_5 =
i * (unsigned int) 0xcccccccd;
return (n_div_5 < 0x33333334);//<=>n_div_5 <= 0x33333333
/*
because 5 * 0xcccccccd == 0x4 0000 0001 and
(uint32_t) 0x400000001 == 1
*/
}
同じルールに従って、「n」による分割可能性テストの結果を取得するには、次のことを実行できます。数値に0x1 0000 0000-(1/n)* 0xFFFFFFFFを掛けて、(1/n)* 0xFFFFFFFFと比較します。
対応するものは、一部の値では、テストしたいすべての32ビットの数値に対して正しい結果を返すことができないことです。たとえば、7で割り切れる場合です。
0x100000000-(1/n)* 0xFFFFFFFF = 0xDB6DB6DCおよび7 * 0xDB6DB6DC = 0x6 0000 0004を取得しました。値の4分の1のみをテストしますが、減算を使用すれば確実に回避できます。
その他の例:
11 * 0xE8BA2E8C = A0000 0004、値の4分の1
17 * 0xF0F0F0F1 = 10 0000 0000 1 0xF0F0F0Fと比較1すべての値!
等、それらの間の自然数を組み合わせることにより、すべての数をテストすることもできます。
追加した数値のすべての桁が3、6、または9となる場合、数値は3で割り切れます。たとえば、3693は3で割り切れます。3+ 6 + 9 + 3 = 21および2 + 1 = 3および3 3で割り切れる.
inline bool divisible3(uint32_t x) //inline is not a must, because latest compilers always optimize it as inline.
{
//1431655765 = (2^32 - 1) / 3
//2863311531 = (2^32) - 1431655765
return x * 2863311531u <= 1431655765u;
}
一部のコンパイラでは、これは通常の方法よりも高速です:x % 3
。続きを読む こちら 。
数値の桁数の合計がすべて3で割り切れる場合、数値は3で割り切れるので、各桁を入力数値の部分文字列として取得し、それらを合計することができます。その後、結果が1桁になるまでこのプロセスを繰り返します。
これが3、6、または9の場合、数は3で割り切れます。
数字の合計が3で割り切れる場合、数値は3で割り切れる。この定義は、1桁になるまで再帰的に使用できる。結果が3、6、または9の場合、元の数は3で割り切れます。それ以外の場合は割り切れません。
例:33333 => 15(3 + 3 + 3 + 3 + 3)=> 6(1 + 5)なので、33333は3で割り切れます。
分割可能性ルール を参照
数値が3で割り切れるかどうかをチェックするC#ソリューション
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int num = 33;
bool flag = false;
while (true)
{
num = num - 7;
if (num == 0)
{
flag = true;
break;
}
else if (num < 0)
{
break;
}
else
{
flag = false;
}
}
if (flag)
Console.WriteLine("Divisible by 3");
else
Console.WriteLine("Not Divisible by 3");
Console.ReadLine();
}
}
}