2016-05-25 8 views
1

漠然としたタイトルのために大いに謝りますが、私は詳しく述べる必要があります。ここで私はhttp://ariya.ofilabs.com/2013/07/prime-numbers-factorial-and-fibonacci-series-with-javascript-array.htmlに読み、問題のコードは、次のとおりです。私たちはいくつかの出力を見ることができるようにこのJavaScript関数はなぜ機能しますか?

function isPrime(i) { 
    return (i > 1) && Array.apply(0, Array(1 + ~~Math.sqrt(i))). 
    every(function (x, y) { 
     console.log(x + ' ' + i % y); 
     return (y < 2) || (i % y !== 0) 
    }); 
} 

isPrime(23); 
isPrime(19); 
isPrime(188); 

楽しみのためだけに、私はこれらのログを追加しました:

undefined NaN 
undefined 0 
undefined 1 
undefined 2 
undefined 3 
undefined NaN 
undefined 0 
undefined 1 
undefined 1 
undefined 3 
undefined NaN 
undefined 0 
undefined 0 

これは、すべて私が持っている最初の時間ですapplyevery見て、そう私と一緒にクマが、私の理解がapplyは、基本的には、第1引数はそのthisの代替であり、第二は、出力されたアレイの機能を呼び出していることです...それは有用であろうと思わないだろう決して、しかし、この機能はうまくいくようです...

ここでは、問題の番号の平方根に等しい長さの配列を作成しているようです。私は平方根が問題の数の可能な最大要因であるので意味があると思います。

> var i = 23; 
undefined 
> Array.apply(0, Array(1 + ~~Math.sqrt(i))); 
[ undefined, undefined, undefined, undefined, undefined ] 

グレート、それは5 undefinedの配列です:我々は最初の数、たとえば、のためにその配列を記録した場合

OK、ここからので、それは次のようになります。さて、ここから、everyメソッドは、その配列のすべての要素がコールバック関数のテスト(または何でも)を渡すかどうかをチェックすることになっています。

Microsoftのドキュメントをevery方法のための3つの可能な引数を指定しています

  • インデックス
  • 配列

したがって、この例ではxは、値、すなわちundefinedですyがインデックスです。

私たちの出力は、その結論に同意します。しかし、私はまだネストされたreturn文については曖昧です(最低のものが返され、親も戻りますか?)、ここで||演算子(最初のテストが合格すれば、すべてのループは停止しますか?働く


EDIT

ログはX、Yしないでなければなりません。私のミス:

console.log(y + ' ' + i % y); -> console.log(x + ' ' + i % y); 

EXPLANATION

ので、私はこのコードを渡って来たのか、あなたは尋ねますか?

function isPrime(n) { 
    for (var i = 2.0; i < Math.sqrt(n); i++) { 
     if (n % i === 0.0) { 
      return false; 
     } 
    } 
    return true; 
} 

public static boolean isPrime(double num) { 
    for (double i = 2.0; i < sqrt(num); i++) { 
     if (num % i == 0.0) { 
      return true; 
     } 
    } 
    return false; 
} 

やPython

def isPrime(num): 
    x = 2 
    isPrime = True 
    while x < math.sqrt(num): 
     if num % x == 0: 
      isPrime = False 
      break 
     x = x + 1 
    return isPrime 

やJSしかし、私がしたかったと言う:まあ、もちろん、Javaでプライムをチェックする最も簡単な方法は、次のようになります600851475143のような数字の最大の素因数を調べるこれらのループ方法は時間がかかりすぎるでしょうか?私は、この「ハック」は、整数や浮動小数点の代わりに配列を使用しているため、それが効率的ではないかもしれないと思っていますが、それでもなお問題を解決するための効率的な方法を探していました。

+1

私は間違いなくあなたと同じ 'はconsole.log()'出力を得ることはありません、と私は驚いていませんよ。 'y'は決して' undefined'であってはなりません。 – Pointy

+0

あなたが見つけたブログには、その 'Array()'トリックに関する記事があります。 – Pointy

+0

うん、私はブログを読んだが、この部分に立ち往生した。それを理解できないので、ここに来ました。 – pward

答えて

4

このポストのコードは基本的には駄目です。ハッキングを使用しながらコードを書くように人々に教えることはゴミです。はい、ハッキングは最適化されていますが、教育者はそれに依存しないソリューションを示すべきです。

私はまだネストされたreturn文(IF LOについてあいまいだハック1

// the 0 isn't even relevant here. it should be null 
Array.apply(0, Array(1 + ...)) 

ハック2

// This is just Math.floor(x), but trying to be clever 
~~x 

ハック3

// this is an outright sin; totally unreadable code 
// I bet most people don't know the binding precedence of % over + 
y + ' ' + i % y 

// this is evaluated as 
y + ' ' + (i % y) 

// example 
2 + ' ' + (5 % 2) //=> "2 1" 

西1リターンは、その親も返さない?)、

returnのみ

に文が存在する関数を返し||ここで、操作者(最初のテストに合格した場合、すべてのループ停止していますか?)

Array.prototype.everyとすぐにコールバックがfalseを返すようfalseを返します。 falseがコールバックから返されない場合、.everyは `trueを返します。ここで

function isEven(x) { return x % 2 === 0; } 
[2,4,5,6].every(isEven); //=> false, stops at the 5 
[2,4,6].every(isEven); //=> true 

[1,2,3,4,5,6].every(x=> {console.log(x, x<4); return x<4;}); 
// 1 true 
// 2 true 
// 3 true 
// 4 false 
//=> false 

.every短絡の例のコールバックがfalseを返したら、止まるかを参照してください?要素5および6は評価されていません。

...これは一般的な動作です。

&&Array.prototype.someのような作品のArray.prototype.every||種類などの作品のようなもの。

&&は、最初にfalseに遭遇するとすぐにfalseを返します。言い換えれば、すべて引数はtrueであると予測します。

||は、最初にtrueに遭遇するとすぐにtrueを返します。換言すれば、の引数はtrueであると予測します。関連

short circuit evaluation

+0

* crap *の特性に同意します。これはちょっとした巧妙なトリックですが、ブログのサンプルコードを投稿する最初のルールに違反しています。コードが悪ければ、いつかは生存に不可欠なソフトウェアに埋め込む人の数が増えます。 – Pointy

+0

さて、なぜ各インデックス0メンバーが '(y <2)'に対して真を返さないのでしょうか? – pward

+0

私がこのブログに来た唯一の理由は、オイラー・プロジェクトに投稿された数字の素因数をチェックするために使っていたforループが長すぎる時間を費やしていたからです。 – pward

関連する問題