2011-12-29 56 views
2

我知道大多數情況下指數是O(log n)或更差,但是我試圖理解數字是如何表示自己的。以JavaScript的,例如,因爲它有幾個本地的數字格式:你能比O(log n)獲得10的冪更快嗎?

100000 === 1E5 && 100000 === 0303240 
>>> true 

內部,是不是所有最終被存儲和處理存儲在內存中的二進制值?如果是這樣,機器是否能夠像八進制一樣快地存儲小數和科學符號表示?

因此,您認爲+("1E" + n)會比Math.pow(10, n)更快嗎?

大多數情況下,這個問題是關於1E(n)是如何工作的,但在試圖自己思考答案時,我更加好奇數字是如何解析並存儲在第一位的。我希望你能提供任何解釋。

回答

1

但我迷路了,試圖瞭解數字如何表示自己。以JavaScript爲例,因爲它有幾種本地數字格式:

在內部,它們都不是最終被存儲和操作爲存儲在內存中的二進制值嗎?

是的在JavaScript中,只有一個號碼鍵入一個64位浮點類型因此

1 === 1.0 

http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference

如果是這樣,是能夠存儲小數和科學記數法的機表示與八進制一樣快?

是的,因爲只有一種類型。 (也許有一個微小的差異,但它應該可以忽略不計)

但是,對於這種特定情況下,可以表示的數字是有限制的〜1e300,因此運行時間爲O(〜300)= O(1 )所有其他數字都表示爲+/- Infinity。

因此,你期望+(「1E」+ n)比Math.pow(10,n)更快嗎?

不完全! 1E100比Math.pow(10,n)更快 然而+(「1E」+ n)比Math.pow(10,n)慢。 不是因爲字符串和內存分配,而是因爲JS解釋器必須解析字符串並將其轉換爲數字,並且比本機Math.pow(num,num)操作要慢。

jsperf test

+0

感謝精心佈置,很好的支持答案。 – kojiro 2011-12-29 19:25:32

3

我不認爲字符串操作可能會更快,因爲至少連接會創建一個新的對象(內存分配,更多的GC工作),Math.pow通常來自單機指令。此外,一些現代JS虛擬機做熱點優化,從javascript生成機器碼。對於Math.pow有機會,但幾乎不可能的字符串魔術。

如果您100%確定Math.pow在您的應用程序中運行緩慢(我無法相信它),您可以使用數組查找,它應該儘可能快地工作:[1,10,100,1000,10000,...][n]。陣列相對較小,複雜度爲O(1)

+0

喜歡的數組覆蓋範圍。 [10^1,10^2,...](我知道^在JS中不是pow) – 2011-12-29 14:38:58

+0

@TomRoggero Better'[1e0,1e1,1e2,1e3,...]' – kan 2011-12-29 14:55:52

0

Math.pow不區分數字,所以對於每個數字它都一樣慢,只要解釋器​​不針對整數進行優化。它可能只分配幾個花車來運行。我忽略瞭解析時間。

「1E」+ n將分配2〜3個字符串對象,這些對象可能具有相當大的內存開銷,銷燬中間體並將其重新分解爲數字。不可能比pow更快。我再次無視分析時間。

1

我在選項上運行了jsperf

var sum = 0; 
for (var i = 1; i < 20; ++i){ 
    sum += +("1E" + i); 
} 

由於字符串連接緩慢。

var sum = 0; 
for (var i = 0; i < 20; ++i){ 
    Math.pow(10, i); 
} 

因此速度更快,因爲它只對數字進行操作。

var sum = 0; 
sum += 1e0; 
sum += 1e1; 
... 
sum += 1e19; 

是最快的,但只有可能因爲1ex爲一個常數是預先計算的值。

爲了獲得最佳性能,您可能需要爲自己預先計算答案。

相關問題