Programming

Math.random ()을 호출하는 함수가 순수합니까?

procodes 2020. 8. 2. 18:46
반응형

Math.random ()을 호출하는 함수가 순수합니까?


다음은 순수한 기능입니까?

function test(min,max) {
   return  Math.random() * (max - min) + min;
}

내 이해는 순수한 기능이 다음 조건을 따른다는 것입니다.

  1. 매개 변수에서 계산 된 값을 리턴합니다.
  2. 반환 값을 계산하는 것 외에 다른 작업을 수행하지 않습니다

이 정의가 정확하면 내 함수가 순수한 함수입니까? 아니면 순수한 함수가 무엇이 잘못되었는지 이해하고 있습니까?


아뇨. 동일한 입력이 주어지면이 함수는 다른 값을 반환합니다. 그런 다음 입력과 출력을 매핑하는 '테이블'을 만들 수 없습니다.

순수한 기능에 대한 Wikipedia 기사에서 :

함수는 항상 동일한 인수 값이 주어지면 동일한 결과 값을 평가합니다. 기능 결과 값은 프로그램 실행이 진행되는 동안 또는 프로그램의 다른 실행간에 변경 될 수있는 숨겨진 정보 또는 상태에 의존 할 수 없으며 I / O 장치의 외부 입력에 의존 할 수도 없습니다.

또한 이 스레드 에서 설명한대로 순수한 함수를 입력 및 출력의 맵핑을 나타내는 테이블로 대체 할 수 있습니다 .

이 함수를 다시 작성하고 순수한 함수로 변경하려면 임의의 값을 인수로 전달해야합니다

function test(random, min, max) {
   return random * (max - min) + min;
}

그런 다음이 방법으로 호출하십시오 (예 : 2와 5를 최소 및 최대로).

test( Math.random(), 2, 5)

귀하의 질문에 대한 간단한 대답 은 규칙 # 2Math.random()위반한다는 것입니다.

다른 많은 답변 Math.random()은이 기능이 순수하지 않다는 것을 의미한다고 지적했습니다 . 그러나 Math.random() 오염 기능을 사용하는 기능을 오염시키는 가치가 있다고 생각 합니다.

모든 의사 난수 생성기와 마찬가지로 Math.random()"시드"값으로 시작합니다. 그런 다음이 값을 낮은 수준의 비트 조작 체인 또는 다른 연산에서 시작하여 예측할 수없는 (실제로는 랜덤 하지 않은 ) 출력으로 시작합니다.

JavaScript에서 관련된 프로세스는 구현에 따라 다르며 다른 많은 언어와 달리 JavaScript는 시드를 선택할 수있는 방법을 제공 하지 않습니다 .

구현은 초기 시드를 난수 생성 알고리즘으로 선택합니다. 사용자가 선택하거나 재설정 할 수 없습니다.

이것이 바로이 함수가 순수하지 않은 이유입니다. JavaScript는 본질적으로 제어 할 수없는 암시 적 함수 매개 변수를 사용합니다. 다른 곳에서 계산되고 저장된 데이터에서 해당 매개 변수를 읽고 있으므로 정의의 규칙 # 2를 위반합니다.

이 기능을 순수한 함수로 사용하려면 여기에 설명 된 대체 난수 생성기 중 하나를 사용할 수 있습니다 . 그 발전기를 호출하십시오 seedable_random. 하나의 매개 변수 (시드)를 사용하여 "임의"숫자를 리턴합니다. 물론이 숫자는 전혀 무작위가 아닙니다. 그것은 씨앗에 의해 독특하게 결정됩니다. 이것이 이것이 순수한 기능인 이유입니다. seedable_random입력을 기반으로 출력을 예측하는 것이 어렵다는 점에서 출력은 "임의"입니다.

이 함수의 순수한 버전은 세 가지 매개 변수 를 가져야합니다 .

function test(min, max, seed) {
   return  seedable_random(seed) * (max - min) + min;
}

주어진 3 중 (min, max, seed)파라미터에 대해 항상 동일한 결과를 반환합니다.

출력 seedable_random실제로 무작위가 되길 원한다면 시드를 무작위 화하는 방법을 찾아야합니다! 그리고 어떤 전략을 사용하든 불가피하게 순수하지 않을 수 있습니다. 왜냐하면 함수 외부의 소스에서 정보를 수집해야하기 때문입니다. mtraceurjpmc26이 알려주 듯이 여기 에는 하드웨어 난수 생성기 , 렌즈 캡이있는 웹캠 , 대기 소음 수집기 , 심지어 용암 램프 와 같은 모든 물리적 접근 방식이 포함됩니다 . 이러한 모든 기능은 함수 외부에서 계산 및 저장된 데이터를 사용합니다.


순수한 함수는 반환 값이 부작용이없는 입력 값에 의해서만 결정되는 함수입니다.

Math.random을 사용하면 입력 값 이외의 값으로 값을 결정하게됩니다. 순수한 기능이 아닙니다.

출처


아니요, 출력은 제공된 입력 (Math.random ()은 모든 값을 출력 할 수 있음) 에만 의존하지 않기 때문에 순수한 함수는 아니지만 순수한 함수는 항상 동일한 입력에 대해 동일한 값을 출력해야합니다.

함수가 순수하면 동일한 입력으로 여러 호출을 최적화하고 이전 호출의 결과를 재사용하는 것이 안전합니다.

추신 : 적어도 저와 다른 많은 사람들에게 redux는 순수한 기능 이라는 용어를 대중적으로 만들었습니다 . redux 문서에서 바로 :

감속기 안에서는 절대로하지 말아야 할 것들 :

  • 그 주장을 바꾸십시오.

  • API 호출 및 라우팅 전환과 같은 부작용을 수행하십시오.

  • Date.now () 또는 Math.random ()과 같이 순수하지 않은 함수를 호출하십시오.


From mathematical point of view, your signature is not

test: <number, number> -> <number>

but

test: <environment, number, number> -> <environment, number>

where the environment is capable of providing results of Math.random(). And actually generating the random value mutates the environment as a side effect, so you also return a new environment, which is not equal to the first one!

In other words, if you need any kind of input that does not come from initial arguments (the <number, number> part), then you need to be provided with execution environment (that in this example provides state for Math). The same applies to other things mentioned by other answers, like I/O or such.


As an analogy, you can also notice this is how object-oriented programming can be represented - if we say, e.g.

SomeClass something
T result = something.foo(x, y)

then actually we are using

foo: <something: SomeClass, x: Object, y: Object> -> <SomeClass, T>

with the object that has its method invoked being part of the environment. And why the SomeClass part of result? Because something's state could have changed as well!


Pure functions always return the same value for same input. Pure functions are predictable and are referential transparent which means that we can replace the function call with the output returned and it will not change the working of the program.

https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md


In addition to the other answers that correctly point out how this function is non-deterministic, it also has a side-effect: it will cause future calls to math.random() to return a different answer. And a random-number generator that doesn’t have that property will generally perform some kind of I/O, such as to read from a random device provided by the OS. Either is verboten for a pure function.


No, it isn't. You can't figure out the result at all, so this piece of code can't be tested. To make that code testable, you need to extract the component that generates the random number:

function test(min, max, generator) {
  return  generator() * (max - min) + min;
}

Now, you can mock the generator and test your code properly:

const result = test(1, 2, () => 3);
result == 4 //always true

And in your "production" code:

const result = test(1, 2, Math.random);

Would you be fine with the following:

return ("" + test(0,1)) + test(0,1);

be equivalent to

var temp = test(0, 1);
return ("" + temp) + temp;

?

You see, the definition of pure is a function whose output does not change with anything other than its inputs. If we say that JavaScript had a way to tag a function pure and take advantage of this, the optimizer would be allowed to rewrite the first expression as the second.

I have practical experience with this. SQL server allowed getdate() and newid() in "pure" functions and the optimizer would dedupe calls at will. Sometimes this would do something dumb.

참고URL : https://stackoverflow.com/questions/47035166/is-a-function-that-calls-math-random-pure

반응형