プロス番号ですか?


37

フランソワプロスにちなんで名付けられたプロス番号は、次のように表現できる番号です。

N = k * 2^n + 1

where kは奇数の正の整数で、nはのような正の整数です2^n > k。より具体的な例を使用してみましょう。テイク3. 3はProth番号です。

(1 * 2^1) + 1

そして2^1 > 1満足しています。5はProth番号でもあります。

(1 * 2^2) + 1

そして2^2 > 1満足しています。ただし、7はProth番号ではありません。フォームに書き込む唯一の方法N = k * 2^n + 1

(3 * 2^1) + 1

そして2^1 > 3満足していません。

あなたの挑戦は非常に単純です:あなたは、正の整数を与えられて、それがプロス数であるかどうかを決定するプログラムまたは関数を書かなければなりません。入力は合理的な形式で行うことができ、Proth番号の場合は真実の値を出力し、そうでない場合は偽の値を出力する必要があります。言語に「Proth-number detection」機能がある場合、それらを使用できます。

テストIO

1000までの最初の46個のProth番号を以下に示します。(A080075

3, 5, 9, 13, 17, 25, 33, 41, 49, 57, 65, 81, 97, 113, 129, 145, 161, 177, 193, 209, 225, 241, 257, 289, 321, 353, 385, 417, 449, 481, 513, 545, 577, 609, 641, 673, 705, 737, 769, 801, 833, 865, 897, 929, 961, 993

他のすべての有効な入力は、偽の値を与える必要があります。

いつものように、これはコードゴルフなので、標準的な抜け穴が適用され、バイト単位の最短回答が勝ちます!


数論の面白い事実:

メルセンヌ素数ではない最大の知られている素数は19249 * 2^13018586 + 1であり、これは偶然にもプロス数です!

回答:


41

ゼリー、5 バイト

’&C²>

オンラインでお試しください!または、すべてのテストケースを確認します

バックグラウンド

してみましょうjは厳密に正の整数です。j + 1は、jのすべての後続設定ビットと隣接する未設定ビットを切り替えます。たとえば、10011 2 + 1 = 10100 2です。

以降〜J = - (J + 1)= -j - 1-j =〜J + 1、そう-nのビット単位NOTするために、上記適用J(トグル全てこうして最後の前にすべてのビットをトグル、ビット)1

取ってJ&-j -ビット単位のJ及び-j -最後のセットのビットの前と後の全てのビットが(に等しくないので無効化されているJおよび-j従って最高パワー得)2分割Jを均等にします。

入力の場合はN、我々はに上記適用する1 - N見つけるために、2 のn、最高のパワー2分割し、1 - Nをm = N-1の場合、-m =-(N-1)= 1-Nなので、(N-1)&(1-N)2 nを生成します。

テストするのは、2 n > kかどうかだけです。場合K> 0、これが真である場合にのみ(2 N2 > K2 N、場合に限り、それ自体真である(2 N2 ≥K2 N + 1 = N

最後に、(2 n2 = N = k2 n + 1の場合、両側のパリティが一致できるように2 nは奇数(1)でなければならず、k = 0およびN = 1を意味します。この場合、&(1 - N)= 0 0 = 0 - (1 N)および((N - 1)・(1 - N))2 = 0 <1 = N

したがって、((N-1)&(1-N))2 > Nは、NがProth数である場合にのみ真です。

使い方

’&C²>  Main link. Argument: N

’      Decrement; yield N - 1.
  C    Complement; yield 1 - N.
 &     Take the bitwise AND of both results.
   ²   Square the bitwise AND.
    >  Compare the square to N.

わあ。それは信じられない
明るい

46

Python、22バイト

lambda N:N-1&1-N>N**.5

これは私のゼリーの答えの移植です。Ideoneでテストします。

使い方

してみましょうjは厳密に正の整数です。j + 1は、jのすべての後続設定ビットと隣接する未設定ビットを切り替えます。たとえば、10011 2 + 1 = 10100 2です。

以降〜J = - (J + 1)= -j - 1-j =〜J + 1、そう-nのビット単位NOTするために、上記適用J(トグル全てこうして最後の前にすべてのビットをトグル、ビット)1

取ってJ&-j -ビット単位のJ及び-j -最後のセットのビットの前と後の全てのビットが(に等しくないので無効化されているJおよび-j従って最高パワー得)2分割Jを均等にします。

入力の場合はN、我々はに上記適用する1 - N見つけるために、2 のn、最高のパワー2分割し、1 - Nをm = N-1の場合、-m =-(N-1)= 1-Nなので、(N-1)&(1-N)2 nを生成します。

テストするのは、2 n > kかどうかだけです。場合K> 0、これが真である場合にのみ(2 N2 > K2 N、場合に限り、それ自体真である(2 N2 ≥K2 N + 1 = N

最後に、(2 n2 = N = k2 n + 1の場合、両側のパリティが一致できるように2 nは奇数(1)でなければならず、k = 0およびN = 1を意味します。この場合、&(1 - N)= 0 0 = 0 - (1 N)および((N - 1)・(1 - N))2 = 0 <1 = N

したがって、((N-1)&(1-N))2 > Nは、NがProth数である場合にのみ真です。

浮動小数点の不正確さを無視すると、これはN-1&1-N>N**.5実装のコードと同等です。


23
私は頻繁にMath.SEを使用しており、90年代のサイトのように見えるのではなく、このサイトで美しいLaTeXを望んでいます
...-qwr

これは私のお気に入りです。
Qix


9

Mathematica、50 48 45 40 38 35 31 29バイト

Mathematicaは一般的にゴルフをコーディングするのに苦労しますが、時には物事を本当に見栄え良くするビルトインがあります。

1<#<4^IntegerExponent[#-1,2]&

テスト:

Reap[Do[If[f[i],Sow[i]],{i,1,1000}]][[2,1]]

{3, 5, 9, 13, 17, 25, 33, 41, 49, 57, 65, 81, 97, 113, 129, 145, 161, 177, 193, 209, 225, 241, 257, 289, 321, 353, 385, 417, 449, 481, 513, 545, 577, 609, 641, 673, 705, 737, 769, 801, 833, 865, 897, 929, 961, 993}

編集:実際には、デニスのビット単位のANDアイデアを盗むと、23 22 20バイトになります。

Mathematica、23 22 20バイト(A Simmonsに感謝)

BitAnd[#-1,1-#]^2>#&

2
プログラミングパズルとコードゴルフへようこそ!:)
アドナン

1
で始まる必要はありませんg=、純粋な関数は大丈夫です!
シモンズ

お、可愛い。今それを修正しました。
マイケルリー

ところで、テストはに大幅に簡素化できますSelect[Range@1000,f]
numbermaniac

8

05AB1E14 10バイト

4バイトを節約してくれたEmignaに感謝します!

コード:

<©Ó¬oD®s/›

CP-1252エンコードを使用します。オンラインでお試しください!

説明:

説明のために、番号241を使用しましょう。まず、で数値を1減らします<。結果は240になります。ここで、を使用して(重複した)素因数を計算しÒます。主な要因は次のとおりです。

[2, 2, 2, 2, 3, 5]

それらを2つの部分に分割しました。を使用して2Q·0K、2つのリストを取得します。

[2, 2, 2, 2]

では®2K、我々は残りの番号のリストを取得します:

[3, 5]

最後に、両方の製品を取ります。[2, 2, 2, 2]結果1615[3, 5]結果の積。

16 > 15以来、このテストケースは真実です。


<©Ó¬oD®s/›または<DÓ0èoDŠ/›10用
Emigna

@Emignaそれは天才です!ありがとう:)。
アドナン

7

脳フラック460 350 270 266の 264 188 176バイト

オンラインでお試しください!

({}[()])(((<>()))){{}([(((({}<(({}){})>){}){})<>[({})(())])](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}}(<{}{}>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<>)

説明

プログラムは、N-1より大きい2のべき乗を見つけるまで、2と4のべき乗を行います。それを見つけると、モジュロを使用して2のべき乗でN-1の可分性をチェックし、結果を出力します。

({}[()])      #Subtract one from input
(((<>())))    #Put three ones on the other stack
{
 {}           #Pop the crap off the top
 ([(
  ((({}<(({}){})>){}){}) #Multiply the top by four and the bottom by two
  <>[({})(())])](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{} #Check if the power of four is greater than N-1
}
(<{}{}>) #Remove the power of 4
<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>) #Modulo N-1 by the power of two

このプログラムはスタッククリーンではありません。余分な4バイトを追加すると、スタックをクリーンにすることができます。

({}[()])(((<>()))){{}([(((({}<(({}){})>){}){})<>[({})(())])](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}}(<{}{}>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>)

5

MATL、9バイト

qtYF1)EW<

真実の出力は1です。偽の0出力または空の出力。(空の出力を生成する入力は1and のみで2、残りはまたはのいずれ0かを生成します1)。

オンラインでお試しください!

説明

ましょう、xは入力を示します。ましょうyは 2、その分割の最大電力であるX -1、およびZ =を(X -1)/ Yzは自動的に奇数になることに注意してください。次いで、xは Proth番号である場合にのみ、Y > Z、または同等であれば、Y 2 > X -1。

q    % Input x implicitly. Subtract 1
t    % Duplicate
YF   % Exponents of prime factorization of x-1
1)   % First entry: exponent of 2. Errors for x equal to 1 or 2
E    % Duplicate
W    % 2 raised to that. This is y squared
<    % Is x-1 less than y squared? Implicitly display

5

Brachylog、28バイト

>N>0,2:N^P:K*+?,P>K:2%1,N:K=

オンラインでお試しください!

すべてのテストケースを一度に検証します。 (少し変更されています。)

説明

Prologの派生物であるBrachylogは、物事の証明が非常に得意です。

ここでは、これらのことを証明します。

>N>0,2:N^P:K*+?,P>K:2%1,N:K=

>N>0                           input > N > 0
     2:N^P                     2^N = P
         P:K*+?                P*K+1 = input
                P>K            P > K
                  K:2%1        K%2 = 1
                        N:K=   [N:K] has a solution

5

Haskell、55 46バイト

f x=length [x|k<-[1,3..x],n<-[1..x],k*2^n+1==x,2^n>k]>0

編集:nimiのおかげで、現在46バイト

f x=or[k*2^n+1==x|k<-[1,3..x],n<-[1..x],2^n>k]

4
プログラミングパズルとコードゴルフへようこそ!
デニス

ありがとう!しばらくここに潜んでいました。ちなみに、ゼリーは超クールです。私は学ぶことがしたいが、残念ながら、私は本当に理解していない
X88B88

2
一般的なヒント:内包表記によって作成されたリストの長さにのみ興味がある場合は、を使用できますsum[1| ... ]。ここで、さらに進んで、等式テストをの前に移動し、それらのいずれかが真|であるorかどうかを確認できますf x=or[k*2^n+1==x|k<-...,n<-...,2^n>k]
-nimi

ワオ。素晴らしいヒント。間違いなく修正します。
-X88B88

2
Jellyの学習に興味がある場合は、wikiをチェックするか、Jellyルームに参加してください。
デニス

5

ECMAScript Regex、48 43 41バイト

NeilとH.PWizの正規表現(両方ともECMAScriptフレーバー)は、それ自体が美しいです。それを行う別の方法があります。かなりきれいな偶然の一致により、ニールよりも1バイト多く、H.PWizの推奨ゴルフ(感謝!)で、H.PWiz より 1バイト少なくなりました。

警告:この正規表現はサイズが小さいにもかかわらず、大きなネタバレが含まれています。初期の数学的洞察を個別に把握することにより、ECMAScript正規表現の単項数学的問題を解決する方法を学ぶことを強くお勧めします。それは私にとって魅力的な旅でした。自分で試してみたいと思う人、特に数論に興味のある人のためにそれを台無しにしたくありません。スポイラーでタグ付けされた推奨される問題を1つずつ解決するためのリストについては、以前の投稿参照してください

したがって、高度な単項正規表現の魔法を台無しにしたくない場合は、これ以上読んではいけません。この魔法を自分で理解しようとするなら、上記のリンクに掲載されているECMAScript正規表現の問題を解決することから始めることを強くお勧めします。

したがって、この正規表現は非常に簡単に機能します。1を引くことから始まります。次に、最大の奇数因子kを見つけます。次に、kで除算します(階乗数regex postのスポイラータグ付き段落で簡単に説明した除算アルゴリズムを使用)。結果の商がkよりも大きいという同時主張をこっそりと行います。部門が一致する場合、Proth番号があります。そうでない場合、私たちはしません。

私はによって見出さトリック使用してこの正規表現(→41〜43)から2つのバイトを削除することができた汚れた商が除数に等しいか又はそれより大きいことが保証されている場合には短く分割futherことができます。

^x(?=(x(xx)*)\1*$)((\1x*)(?=\1\4*$)x)\3*$

オンラインでお試しください!


 # Match Proth numbers in the domain ^x*$
 ^
 x                         # tail = tail - 1
 (?=(x(xx)*)\1*$)          # \1 = largest odd factor of tail
 
 # Calculate tail / \1, but require that the quotient, \3, be > \1
 # (and the quotient is implicitly a power of 2, because the divisor
 # is the largest odd factor).
 (                         # \3 = tail / \1, asserting that \3 > \1
     (\1x*)                # \4 = \3-1
     (?=\1\4*$)            # We can skip the test for divisibility by \1-1
                           # (and avoid capturing it) because we've already
                           # asserted that the quotient is larger than the
                           # divisor.
     x
 )
 \3*$
 


1
O_oうわー、わずか48バイト
ASCIIのみ

ニールさんは、デニスよりも鉱山に似ている
H.PWiz

4

ジュリア、16バイト

!x=~-x&-~-x>x^.5

答えといくつかのゴルフのヒントについて@Dennisに感謝します!


それは機能しません。ジュリアで&は、と同じ優先順位を持ち*ます。
デニス

1
そうそう。修正:PIは本当にコードをテストするはずです。
ママファンロール

2
-~-x代わりに使用できます(1-x)。また、の√x代わりにx^.5がありますが、バイトは保存されません。
デニス

4

R、52 50バイト

x=scan()-1;n=0;while(!x%%2){x=x/2;n=n+1};2^(2*n)>x

プログラムは、分割することによって開始されますN-1(ここでは呼ばれるPx)によって2発見するために、できるだけ長く2^n残し、方程式の一部をk=(N-1)/2^n、その後、天気を計算かkに劣っている2^nという事実を利用して、2^n>x/2^n <=> (2^n)²>x <=> 2^2n>x


1
P=最初にプルし、最後を2^n>x5バイトまたは6バイトに変更して保存できます
-user5957401

4

正規表現(ECMAScript)、40 38バイト

デッドコードのおかげで-2バイト

^x(?=((xx)+?)(\1\1)*$)(?!(\1x\2*)\4*$)

オンラインでお試しください!

コメント版:

# Subtract 1 from the input N
^x

# Assert N is even.
# Capture \1 = biggest power of 2 that divides N.
# Capture \2 = 2.
(?=((xx)+?)(\1\1)*$)

# Assert no odd number > \1 divides N
(?!(\1x\2*)\4*$)

うわー、これは非常にクールです。この問題を行うには、さまざまな方法があります!
デッドコード

1
38バイト:^x(?=((xx)+?)(\1\1)*$)(?!(\1x\2*)\4*$)オンラインそれを試してみてください
Deadcode

2

J、10バイト

%:<<:AND-.

@Dennisのビット単位のソリューションに基づいています

入力を受け取りn、Proth番号の場合は1を返し、そうでない場合は0を返します。

使用法

   f =: %:<<:AND-.
   f 16
0
   f 17
1
   (#~f"0) >: i. 100  NB. Filter the numbers [1, 100]
3 5 9 13 17 25 33 41 49 57 65 81 97

説明

%:<<:AND-.  Input: n
        -.  Complement. Compute 1-n
   <:       Decrement. Compute n-1
     AND    Bitwise-and between 1-n and n-1
%:          Square root of n
  <         Compare sqrt(n) < ((1-n) & (n-1))

ほら 私は知りませんでしたAND。クール!
コナーオブライエン

2

Retina 0.8.2、47バイト

\d+
$*
+`(1+)\1
$+0
01
1
+`.10(0*1)$
1$1
^10*1$

k2n+12k±12n+1+1k=1

\d+
$*

単項に変換します。

+`(1+)\1
$+0
01
1

バイナリに変換します。

+`.10(0*1)$
1$1

Proth生成式を逆に繰り返し実行します。

^10*1$

Proth生成式のベースケースと一致します。

編集:Proth番号を単一の正規表現で単項数と直接照合することは実際に可能だと思います。これは現在、単項数がProth数であるかどうかを確認するために、現在のRetinaコードよりも7バイト多く、47バイトかかります。

^.(?=(.+?)(\1\1)*$)(?=((.*)\4.)\3*$).*(?!\1)\3$

2

ECMAScript正規表現、42バイト

^x(?=(x(xx)*)\1*$)(?=(x+?)((\3\3)*$))\4\1x

オンラインでお試しください!(Retinaを使用)

基本的に1を引き、可能な最大の奇数で除算し、k少なくともk+1残りが残っていることを確認します。

私の正規表現はニールが答えの最後に与えるものと非常に似ていることがわかります。のx(xx)*代わりに使用します(x*)\2x。そして、私はチェックするために短い方法を使用しますk < 2^n


うわー、これは素晴らしいです!とてもうまくできました。あなたが変更することで、少し速くそれを作ることができることに注意してください(\3\3)*)$(\3\3)*$)
Deadcode

そのRetinaコードで素晴らしい仕事をしました。私は知りませんでした$=$.=。さらに改善できる
デッドコード

2
@Deadcodeヘッダーとフッターを選択する場合は、さらに改善してください
ニール

@Neilそれは良いゴルフのように見えますが、残念ながらバグがあるようです。 単一の数字を試してください。彼らは動作しません。
デッドコード

1
@Deadcode申し訳ありませんが、単一の数字が「仕様」の一部であることに気付いていませんでした。
ニール

2

Brain-Flak、128バイト

({<{({}[()]<(([{}]())<>{})<>>)}{}>{{}(<>)}{}}<><(())>){([()]{}<(({}){})>)}{}([({}[{}(())])](<>)){({}())<>}{}{((<{}>))<>{}}{}<>{}

オンラインでお試しください!

古いBrain-Flakソリューションとは非常に異なるアルゴリズムを使用しました

基本的に、偶数に達するまで2で割ります(切り上げ)。次に、最後の除算の結果と2を除算した回数の累乗を比較します。

説明:

({
  # (n+1)/2 to the other stack, n mod 2 to this stack
  <{({}[()]<(([{}]())<>{})<>>)}{}>
  # if 1 (n was odd) jump to the other stack and count the one
  {{}(<>)}{}
#end and push the sum -1, with a one under it
}<>[(())])
#use the one to get a power of two
{([()]{}<(({}){})>)}{}
#compare the power of two with the remainder after all the divisions
([({}[{}(())])](<>)){({}())<>}{}{((<{}>))<>{}}{}<>{}

1

メープル、100バイト(スペースを含む)

IsProth:=proc(X)local n:=0;local x:=X-1;while x mod 2<>1 do x:=x/2;n:=n+1;end do;is(2^n>x);end proc:

読みやすいように間隔を空けて:

IsProth := proc( X )
    local n := 0;
    local x := X - 1;
    while x mod 2 <> 1 do
        x := x / 2;
        n := n + 1;
    end do;
    is( 2^n > x );
end proc:

他のいくつかと同じ考え。Xが2で均等に割り切れなくなるまでXを2で除算し、基準2 ^ n> xを確認します。


1

Javaの1.7、49 43バイト

@charlieのおかげで、さらに6バイトのダストが発生しました。

boolean g(int p){return p--<(p&-p)*(p&-p);}

それを試してみてください!(理想)

等しく長い2つの方法。ここでのほとんどの回答と同様に、クレジットはもちろん@Dennisに送られます。

式の右側のルートを取得します。

boolean f(int p){return(p-1&(1-p))>Math.sqrt(p);}

式の左側に2のべき乗を適用します。

boolean g(int p){return Math.pow(p-1&(1-p),2)>p;}

正の数値が「真」を表し、負の値が「偽」を表すことが許可されている場合、1バイトを削ることができます。

double g(int p){return Math.pow(p-1&(1-p),2)-p;}

残念ながら、「Narrowing Primitive Conversion」のために、これをJavaで簡単に記述して正しい結果を得ることができません。

((p - 1 & (1 - p))^2) > p;

そして、ビット単位の演算子はfloatまたはdoubleでサポートされていないため、「p」を広げようとするとコンパイルエラーが発生します:(


1
f = 47:boolean f(int p){return Math.sqrt(p--)<(p&-p);}
チャーリー

1
g = 43:boolean g(int p){return p--<(p&-p)*(p&-p);}
チャーリー

良いですね!Math.*呼び出しを取り除く方法が必要だと思いました。方法がわかりませんでした!ありがとう!
MH。





0

C(137バイト)

int P(int N){int x=1,n=0,k=1,e=1,P=0;for(;e;n++){for(x=1,k=1;x&&x<N;k+=2){x=2<<n;x=x>k?x*k+1:0;if(x>N&&k==1)e=0;}if(x==N)P=1;}return P;}

試してみてから答えを読むようになりました。

N=k*2^n+1の条件付きで考慮するk<2^nk=1,3,5..およびn=1,2,3..

これn=1kテストすることができます。増加するにつれて、次のようにnさらにk'sテストする必要があります。

n = 1; k = 1

n = 2; k = 1 k = 3

n = 3; k = 1 k = 3 k = 5 k = 7

...

これらの可能性を反復してnk=1得られた数がNより大きく、他の反復が一致しなかった場合、NがProuth数でないことを確認できます。

したがって、私のコードは基本的にNを見つける方法を「強引に」しています。

他の答えを読んで、N-1を2で因数分解しnての条件式を見つけてから、の条件式を作成できることに気付いた後、k<2^nこのメソッドを使用するとコードがより小さく効率的になると思います。

試してみる価値がありました!

与えられたすべての数字といくつかの「非プロウス」数字をテストしました。関数は、数値がProuth数値の場合は1を返し、そうでない場合は0を返します。


0

Javascript ES7、16バイト

x=>x--<(-x&x)**2

@DennisのJelly回答のポートである、私のJulia回答のポート。

@Charlieに2バイトの節約をありがとう!


n=x=>x-1&1-x>x**.5; n(3)私に与える0(実際には入力に関係なく0を与える)
16

どのブラウザ?それだけかもしれません。
ママファンロール

n=x=>x-1&1-x>Math.pow(x,0.5); n(3)
Chrome52。Firefox48でも

Ok-演算子の優先順位です。それが(x-1&1-x)ないと、演算子の優先順位は実際には次のようになります(x-1)&((1-x)>x**.5)
。–

1
-1バイト:x=>x--**.5<(x&-x)またはx=>x**.5<(--x&-x)
チャーリー


0

インク、60バイト

=p(n)
~n-=n>1
~temp x=1
-(k){n%2:{n<x}->->}
~x+=x
~n=n/2
->k

オンラインでお試しください!

@DSkoogのMapleの回答に基づきます -投稿されるのはその種の最初ではありませんでしたが、私が見たのはその種の最初でした。

非ゴルフ

= is_proth(number) =

/* It's easy to check if a number is one less than a Proth number.
   We take the number and divide it by 2 until we can't.
   Once we can't, we've found the smallest possible "k".
   If we also keep track of how many times we divided, we have our corresponding "2^n"
   All we have to do then is compare those
*/

~ number -= (number > 1)            // So, we first subtract one. Except this implementation won't ever halt for 0, so we don't subtract if the input is 1 (this is fine since the desired outputs for inputs 1 and 2 are the same)
~ temp power_of_two = 1             // We declare a variable to store our "2^n"
- (check)
  {
  - number % 2:                     // Once we can't divide by 2 anymore, we've found the smallest possible "k"
    {number < power_of_two}         // At that point, we print whether it's smaller than the "2^n" we found
    ->->                            // And then we return to where we were called from
  }

  ~ number = number / 2             // We keep dividing by 2 until we can't.
  ~ power_of_two += power_of_two    // and update our "2^n" as we go
-> check

0

x86マシンコード、15バイト

4F 89 F8 F7 D8 21 F8 0F AF C0 39 C7 19 C0 C3

これらのバイトは、入力引数(符号なし整数)を受け取る関数を定義します EDI x86システムの標準System V呼び出し規約に従って、レジスターで、次のEAXように結果をレジスターに戻します。すべての x86呼び出し規約。

アセンブラーのニーモニックでは:

4F          dec   edi            ; input -= 1
89 F8       mov   eax, edi       ; \ temp
F7 D8       neg   eax            ; |      =
21 F8       and   eax, edi       ; /        (input & -input)
0F AF C0    imul  eax, eax       ; temp *= temp
39 C7       cmp   edi, eax       ; set CF if (input < temp)
19 C0       sbb   eax, eax       ; EAX = -CF
C3          ret                  ; return with result in EAX
                                 ;  (-1 for Proth number; 0 otherwise)

オンラインでお試しください!

これは非常に簡単なソリューションであり、MegaTomのCバージョンに概念的に似ています。実際、これをCで次のように書くことができます。

unsigned IsProthNumber(unsigned input)
{
    --input;
    unsigned temp  = (input & -input);
    temp          *= temp;
    return (input < temp) ? -1 : 0;
}

ただし、上記のマシンコードは、サイズを最適化するように設定されている場合でも、Cコンパイラから得られるコードよりも優れています。

ここでの唯一の「チート」は、「真の」値として-1を返し、「偽の」値として0を返すことです。このトリックにより、SBB3 バイト命令ではなく2バイト命令を使用できますSETB

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.