1 제한이없는 계승 함수를 만들려고합니다. (호기심에서 벗어났습니다.)이 값은 대용량 인 n
(최대 100000을 시도했는데 작동 할 수 있지만 작동하지 않습니다. 음, LARGE입니다 때문에! 정확성에 대한 출력 값을 확인)스택 오버플로없이 큰 스트림 줄이기
(BigInt(1) to n).reduceRight(_*_)
하지만 난 그냥 reduceRight
위해 요소에 의해 그것을 요소를 필요로하는 동안은 전체 BigInt(1) to n
범위는 메모리에있을 수 있습니다 두려워 해요. BigInt(1) to n
실제로 전체 Range
아니라 게으른 Stream
출력하지만 난 이런 식으로 사용할 수 Stream.range
을 발견 것 같습니다 스칼라의 표준 라이브러리의 코드를 살펴보고 촬영하면
Stream.range[BigInt](BigInt(1), BigInt(n+1)).reduceRight(_*_)
합니다 (n+1
알, 스트림의 범위는 독점) 그것은 하지만 n=100000
내가이 스택 오버 플로우를 얻을 수 (저? 아마 정상 범위가 너무 실제로 Stream
이라고 생각한다이 조금 더 걸리는 몇 가지 이유!에 대한) n=10000
작동
java.lang.StackOverflowError
at java.math.BigInteger.add(Unknown Source)
at scala.math.BigInt.$plus(BigInt.scala:161)
at scala.math.Numeric$BigIntIsIntegral$class.plus(Numeric.scala:28)
at scala.math.Numeric$BigIntIsIntegral$.plus(Numeric.scala:40)
at scala.math.Numeric$BigIntIsIntegral$.plus(Numeric.scala:40)
at scala.math.Numeric$Ops.$plus(Numeric.scala:208)
at scala.collection.immutable.Stream$$anonfun$range$1.apply(Stream.scala:695)
at scala.collection.immutable.Stream$$anonfun$range$1.apply(Stream.scala:695)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:634)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:626)
at scala.collection.LinearSeqOptimized$class.reduceRight(LinearSeqOptimized.scala:130)
at scala.collection.immutable.Stream.reduceRight(Stream.scala:47)
at scala.collection.LinearSeqOptimized$class.reduceRight(LinearSeqOptimized.scala:131)
at scala.collection.immutable.Stream.reduceRight(Stream.scala:47)
at scala.collection.LinearSeqOptimized$class.reduceRight(LinearSeqOptimized.scala:131)
at scala.collection.immutable.Stream.reduceRight(Stream.scala:47)
...
이 reduceRight
이
reduceRight(reduceRight(first, second, op), third, op)...
그리고 이렇게 스택 오버 플로우처럼 자신을 호출하는 것이 명백하다. 나는 tail-call을 최적화하지 않았다고 가정한다. 왜냐하면 tail-call은 값을 반환하기 전에 먼저 줄이거 나 동작하기 때문에 최적화되지 않는다. 그러면이 문제에 어떻게 접근 할 수 있습니까? 기능적 접근 방식을 배제하고 줄이기위한 맞춤형 명령형 코드를 목표로해야합니까?
매우 이상한 점은 큰 n
에 대해 (BigInt(1) to n).reduceRight(_*_)
이 오버플로하지 않는다는 것입니다. 스트림을 사용하면 거의 동일하지만 ... 여기 무슨 일이 있습니까?
다른 답변 (내 경우에도 적용됩니다.) 내 참조하십시오. 또한 : 게으른 범위를 사용하기위한 연습 의미하기 때문에 TCR 사용하여 일반적인 factorial 구현을 피하고 싶습니다. – kaoD
@kaoD - 범위가 필요하지 않으며 마지막 요소부터 시작하지 않습니다. 예제를 참조하십시오 (REPL에 붙여 넣기). –