我正在對Java的慢速Double.toString算法進行優化。我已經成功地重寫了Float.toString(並且速度提高了400%以上)。測試Float.toString的算法很簡單,因爲我可以在煮沸雞蛋的時間內迭代拋出所有可能的值(從Integer.MIN_VALUE到Integer.MAX_VALUE)。如何證明我的Double.toString算法對所有值都是正確的?
但是,以同樣的方式測試Double.toString以獲得準確性將需要我從Long.MIN_VALUE迭代到Long.MAX_VALUE。我可以在所有線程上開始這個測試,並在我的餘生中運行它,我敢打賭它不會完成。
要清楚的是,當我測試這個算法時,我只是把我的結果字符串和調用String.equals對java.lang.Double.toString(double d)的結果。如果它們匹配,我將轉到下一個值。
我對算法的改進主要包括消除不必要的精度。當計算Double.toString時,它使用特殊類型的BigInteger類來執行此操作。但是,我發現通過調整微不足道的位,我仍然可以獲得相同的結果,並且性能顯着提高。
我認爲我可以將所有值修改爲不超過128位(修剪位用一個偏移量替換)而不會失敗我的測試,但是如何在不迭代每個值的情況下證明這一點?
我猜我在問什麼:原始算法的創建者如何知道他們的算法是正確的,而沒有測試每個可能的輸入?
當你說'我打賭它不會完成'時,你是對的,因爲浮點數表示實數,0到1之間實際上有一個**無限**數量。爲了更精確地在任何兩個實數之間存在**無限**其他實數的數量。 –
這樣做的另一個結果是浮點數永遠不能正確表示所有實數,只是適合它的那些。只有**非重要**位,如果存儲在浮點中的當前值只有在0之後的那麼幾個數字,那麼它們適合在那裏並且可以以二進制方式表示。 0。1例如不能以二進制方式呈現,因爲它是1/10。 –
出於實用目的,在Java中有2^64個可能的輸入到Double.toString。其中一些解析爲相同的值(NaN)。一半是消極的。有負值和正值無窮,負值和正值爲零。少數可以使用稍微修改的Long.toString算法來解決。 然而,大多數是通過找到值b和s以使得(b/s)* 10^decExp =雙倍值來計算的。根據需要估算和調整小數指數。 – HesNotTheStig