當前位置:編程學習大全網 - 源碼下載 - Fineui商城源代碼

Fineui商城源代碼

妳好,我是歪的。

最近在stackoverflow上看到壹段代碼。

只是第壹眼看上去很傻,明白了就直接跪下了!

讓我先給妳看看stackoverflow上的這個問題是什麽,然後引出這段代碼:

問題特別簡單,就壹句話:

誰能給我解釋壹下:為什麽這段代碼使用隨機字符串打印出hello world?

代碼也很簡單。讓我把它拿出來給妳看看:

您也可以將上面的代碼直接粘貼到您的運行環境中,並運行它,看看它是否也輸出為hello world:

我就問妳壹句:就算我把所有代碼都給妳,我第壹次看《hello world》的時候妳是不是不知所措?

高贊答道。

高贊的回答也很簡單,就兩句話。

讓我給妳翻譯壹下。這家夥說:

當我們調用Random的構造函數時,我們會得到壹個“種子”參數。比如本例中的:-229985452或者-147909649。

那麽Random將從指定的種子值開始生成隨機數。

並且用相同的種子構造的每個隨機對象將根據相同的模式生成數字。

我沒有看得很清楚,是嗎?

沒關系,我給妳壹段代碼,妳就能恍然大悟上面那段說的是什麽:

這段代碼在我的機器上運行,結果如下:

妳拿著它跑,妳跑的結果壹定是這樣的。

這是為什麽呢?

答案寫在Javadoc上:

在上面的代碼中,兩個-229985452是同壹個種子,三個對nextInt()的調用是同壹個調用序列。

因此,它們生成並返回看似隨機的相同數字。

我們在程序中的正常用法應該是這樣的:

當new Random()時,不指定值。

我們都知道Random是壹種偽隨機算法,在構造的時候指定種子參數是壹種更偽隨機的算法。

因為如果我能猜出妳的種子,或者妳的種子泄露了,那麽理論上我就能猜出妳的隨機數生成序列。

我已經在前面的代碼中演示了這壹點。

前面稍微解釋了壹下“種子”的關鍵點,再回到品嘗的問題上,大概就能看出壹些端倪了。

主要看這個循環裏的代碼。

首先,nextInt(27)定義了當前返回的數字k必須是[0,27]之間的數字。

如果返回0,循環結束;否則,循環結束。然後做壹個類型轉換。

然後是char類型的強制轉換。

當您看到數字變為char類型時,您應該以壹種有條件的方式來考慮ascii代碼:

從ascii代碼表中,我們可以看到“96”是這裏的符號:

因此,以下代碼的範圍是[96+1,96+26]:

也就是[97,122],也就是ascii碼對應的a-z。

所以,我帶妳去反匯編上面的演示代碼。

首先是NewRandom的前五次返回(-229985452)。Nextint (27)如下:

NewRandom的前五次返回(-147909649)。Nextint (27)如下:

所以,當妳查看ascii碼表時,妳可以看到它對應的字母:

現在,至於這個高深莫測的代碼為什麽輸出“hello world”,我心裏是不是很清楚,它就像壹面鏡子?

看穿了,這只是壹個騙局。

然後這個問題下面有個評論,給我看了另壹種打開方式:

您可以指定打印hello world,因此理論上我也可以指定鍵入其他單詞。

比如這位兄弟打了壹個短語:敏捷的褐皮狐貍跳過壹只懶狗。

如果直譯的話,意思是“敏捷的棕狐貍和懶惰的狗雜交”,似乎是壹派胡言。

但是,妳要知道,我的英語水平比較高,在這裏壹眼看到這句話肯定不容易。

所以我查了壹下:

果然有點故事,屬於戲法中的戲法。

看了這位兄弟的快速褐狐例子,我有了新的想法。

既然它能打出所有的字母,我也能打出我想要的特定短語嗎?

我很好,謝謝妳,還有妳。

在這個問題的回答中,“好心人”已經寫出了查找指定單詞對應的seed的功能的代碼。

我直接貼,妳也可以直接拿著用:

所以我在找之前提到的那句話,很簡單:

而且我在跑步的時候,明顯感覺自己花了很多時間在搜索“感謝”這個詞。

為什麽?

我給妳講個故事吧。只有壹句話,妳壹定聽過:

我們這裏的generateSeed方法相當於這只猴子。感謝這個詞就是莎士比亞。

在generateSeed法中,通過26個字母的連續排列組合,總是可以排列出“謝謝”,但只能排列很短的時間。

單詞越長,用的時間越長。

比如我會有壹句恭喜妳,這麽長的壹句話,從00: 05到現在23個小時沒跑出來:

但理論上,只要有足夠的時間,這顆種子是會被找到的。

至此,妳應該完全明白為什麽上面提到的代碼會在隨機字符串的hello world中打印出來了。

妳以為我想帶妳去看源代碼?

不,我主要帶妳吃瓜。

首先,看看隨機無參數構造函數:

好家夥,原來是壹個“無參數”的shell,其實是我自己做了壹個種子,然後調用了參數構造方法。

只是在構建的時候加入了變量“System.nanoTime()”,讓種子看起來有點隨機。

等等,前面不是還有壹個“seedUniquifier”方法嗎?

這個方法是這樣的:

好家夥,第壹次看的時候,頭都大了。這裏面有兩個“神奇的數字”:

這個東西妳也不懂?

永遠不要下定決心,斯達克弗洛

壹搜索就會找到這個地方:

在這個問題中,他說他也對這兩個數字感到不解,他在網上搜了壹圈,相關的資料很少。但是我找到壹篇論文,裏面提到了壹個非常接近的“幻數”:

文中提到的數字如下:

看到了嗎?

這個Java源代碼中的數字少了壹個“1”。發生了什麽事?抄的時候不會出錯吧?

以下是高度贊揚的回答:

“這看起來確實像是壹個錯誤。”

很有意思。如果妳要說這是我哥寫Java源代碼的時候抄的代碼,我會激動的。

馬上去Java Bug的頁面用那串數字搜索,真的是出乎意料:

在對這個bug的描述中,他把我的註意力吸引到了源代碼的這個地方:

原來這個地方的標註代表的是壹篇論文,所以這個數字的來源壹定藏在這篇論文裏。

等等,為什麽我覺得這篇論文的名字有點耳熟?

前壹個stackoverflow中提到的鏈接是壹個紙地址:

看看這篇論文的名字是不是和Java裏的註釋壹樣:

那肯定是壹樣的東西,只是壹個小寫和壹個大寫。

所以,這裏是真錘。真的是第壹次開始用Java寫哥哥的副本數,輸了壹個“1”。

而且,我甚至可以想象,那位兄弟在寫這部分源代碼的時候,把數字“1178349727652981”貼上去,發現:咦,前面怎麽有兩個1?它被復制和刪除了。

至於刪除這個“1”,會帶來什麽問題?

反正這裏有個關聯問題,說並發調用new Random()的隨機性不夠大。

我沒有去研究這個。有興趣可以去看看。我只負責帶妳吃瓜。

於是,基於這個“瓜”,官方對這段代碼進行了壹次修改:

我這裏正好有JDK 15和JDK 8版本的代碼。我壹看,真的是“1”的差別:

而關於隨機數,現在很少用Random。

直接上ThreadLocalRandom,香不香?

什麽,妳拒絕了?

  • 上一篇:經營遊戲最好是開客棧。
  • 下一篇:如何用Python抓取動態頁面信息
  • copyright 2024編程學習大全網