2017-07-12 15 views
18

:787 hakkında özel olan nedir? <a href="http://hackage.haskell.org/package/arithmoi" rel="noreferrer">arithmoi</a> paketini kullanarak GHCi olarak

Math.NumberTheory.Powers.General> :set +s 
Math.NumberTheory.Powers.General> integerRoot 786 ((10^32)^786) 
100000000000000000000000000000000 
(0.04 secs, 227,064 bytes) 
Math.NumberTheory.Powers.General> integerRoot 787 ((10^32)^787) 

beş dakikada yine karşılık vermedi. Neden çok uzun sürüyor?

(bazı ad-hoc test bakıldığında, daha küçük bütün seçimler için 787 daha büyük ve hızlı bütün seçimler için yavaş görünüyor.)

+2

En son arithmoi sürümü ve Mac OS 10.12.5'teki GHCi sürüm 8.0.1 ile çalıştırdığımda,: set + s' seçeneği ile bir segmentasyon hatası alıyorum. ": Set + s" olmadan "Bus error: 10" alırım. Bu "integerRoot" işlevi gibi görünüyor bellek oldukça garip davranır. – Alex

cevap

22

arithmoi implements integerRoot Newton yöntemi ile onun tahmin başlangıç ​​yaklaşık kök alma ve detaylandırarak . İkinci yaklaşım gerçekten kötü bir başlangıç ​​noktası olur, için

> appKthRoot 786 ((10^32)^786) 
100000000000000005366162204393472 

(10) : (10) için, ikinci yaklaşımı gerçekten iyi bir başlangıç ​​noktası olur. gerçekten gerçekten kötü.

> appKthRoot 787 ((10^32)^787) 
1797693134862315907729305190789024733617976978942306572734300811577326758055009 
6313270847732240753602112011387987139335765878976881441662249284743063947412437 
7767893424865485276302219601246094119453082952085005768838150682342462881473913 
110540827237163350510684586298239947245938479716304835356329624224137216 

Aslında bu yaklaşımı burada başlayan her şey için alır.

> let h = 106; k = 786; n = (10^32)^k; !(I# s) = h * k - k in floor (scaleFloat (h - 1) (fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double)) 
100000000000000005366162204393472 

> let h = 106; k = 787; n = (10^32)^k; !(I# s) = h * k - k in floor (scaleFloat (h - 1) (fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double)) 
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216 

ve scaleFloat içine ne olup bittiğini bir göz alarak:

> length $ nub [appKthRoot x ((10^32)^x) | x <- [787..1000]] 
1 

Neyse, the important parts of appKthRoot koyarak, biz olsun

> let h = 106; k = 786; n = (10^32)^k; !(I# s) = h * k - k in fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double 
2.465190328815662 

> let h = 106; k = 787; n = (10^32)^k; !(I# s) = h * k - k in fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double 
Infinity 

Evet, o işe yarar. (10) & yaklaşık olarak; 2 1023.1 bir çifte uyar, ancak (10) & yaklaşık; 2 1024.4 yapmaz.

+2

Bu gerçekten sinir bozucu. Bu büyük "Tamsayı" ilk etapta (ve aritmoi kullanmamın sebebinin bir kısmı) etrafımın altında olmasının sebebi, "Çift" den kaçınmak için gerçekten çok çalışıyorum çünkü ... " –

+0

@DanielWagner: Evet , Neden sadece (h - 1) k'dan fazla ölçeklemediklerini anlamaya çalışıyorum. Bir süreliğine bir düzeltme yapabilirim. – Ryan

+0

@DanielWagner: Örneğin, '' let! A @ (I # a #) = 1024; h = 106; k = 787; n = (10^32)^k; ! (I # s) = h * k - k kat (scaleFloat 105 (from thentnteger (n 'shiftRInteger) (s + # a #)) ** (1/fromIntegral k) * 2 ** (fromIntegral a/k): : Double (Çift)) '' makul bir yaklaştırmaya neden olur ve 'a' yi uygun şekilde ölçeklendirebilirsiniz. Bir meseleyi yükseltmeye değer olabilir. – Ryan

İlgili konular