2012-06-05 26 views
3

假設我想將數字0.011124325465476454轉換爲MATLAB中的字符串。將數值轉換爲MATLAB中的字符串

如果我打

mat2str(0.011124325465476454,100)

我得到0.011124325465476453其不同之處在於最後一個數字。

如果我打num2str(0.011124325465476454,'%5.25f')

我得到0.0111243254654764530000000

其填充與不期望的零和在最後一位數字的不同(3應該是4)。

我需要一種方法來將具有隨機小數位數的數字轉換爲它們的EXACT字符串匹配(無零填充,無最終數字修改)。

有沒有這樣的方式?

編輯:由於我沒有記住Amro和nrz提供的有關精度的信息,因此我添加了一些關於該問題的其他信息。我實際需要轉換的數字來自將其輸出到txt文件的C++程序,它們都是C++ double類型。 [注意:從txt文件輸入數字到MATLAB的部分不是由我編碼的,我實際上不允許修改它以將數字保留爲字符串而不將其轉換爲數字。我只能訪問這個代碼的「輸出」,這是我想要轉換的數字]。到目前爲止,我還沒有得到超過17位小數的​​數字(注意:因此上面提供的示例中,小數點後18位不是非常指示性的)。

現在,如果數15個數字,例如0.280783055069002

然後num2str(0.280783055069002,'%5.17f')mat2str(0.280783055069002,17)回報

0.28078305506900197

這是不準確的數量(見最後位數)。

但如果我打mat2str(0.280783055069002,15)我得到

0.280783055069002這是正確的!

可能有一百萬種方法可以對問題進行「編碼」(例如,創建一個執行轉換的例程),但是當我輸入一個數字時,使用標準的內置MATLAB來獲得理想結果的方式並不是這樣。隨機數的小數(但不超過17);

回答

4

HPF工具箱中,您還可以用數字的MATLAB中的任意精度的工作。

在MATLAB,試試這個:

>> format long g 
>> x = 0.280783054 
x = 
       0.280783054 

正如你可以看到,MATLAB與你所提出的數字寫出來。但MATLAB如何真正「感覺」這個數字呢?它在內部存儲什麼?見sprintf的說什麼:

>> sprintf('%.60f',x) 
ans = 
0.280783053999999976380053112734458409249782562255859375000000 

這是HPF看到的,當它試圖提取從這一數字翻番:

>> hpf(x,60) 
ans = 
0.280783053999999976380053112734458409249782562255859375000000 

事實是,幾乎所有的十進制數字不能表示正好在作爲雙精度浮點運算。 (由於顯而易見的原因,0.5或0.375是該規則的例外)。

但是,當以18位數的小數形式存儲時,我們看到HPF不需要將該數字存儲爲小數形式的二進制近似值。

x = hpf('0.280783054',[18 0]) 
x = 
0.280783054 

>> x.mantissa 
ans = 
    2 8 0 7 8 3 0 5 4 0 0 0 0 0 0 0 0 0 

niels不理解的是,十進制數不以十進制形式存儲爲雙精度型。例如,0.1在內部看起來像什麼?

>> sprintf('%.60f',0.1) 
ans = 
0.100000000000000005551115123125782702118158340454101562500000 

正如你所看到的,matlab不會將它存儲爲0.1。事實上,MATLAB店0.1爲二進制數,這裏實際上...

1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + ... 

或者如果你喜歡

2^-4 + 2^-5 + 2^-8 + 2^-9 + 2^-12 + 2^13 + 2^-16 + ... 

爲了表示0.1完全相同,因爲0.1是這將需要無限多的這樣的術語二進制的重複數字。 MATLAB停止在52位。就像2/3 = 0.6666666666 ...一樣,0.1作爲一個近似值存儲爲一個雙精度值。

這就是爲什麼你的問題真的完全是關於精度和雙重形式的二進制形式。

聊天之後的最終編輯...

的一點是,MATLAB使用雙來表示一個數。因此,它將採用最多15位十進制數字的數字,並能夠使用正確的格式設置將其輸出。

>> format long g 
>> eps 
ans = 
2.22044604925031e-16 

因此,例如...

>> x = 1.23456789
x = 
      1.23456789

而且我們看到,MATLAB已經得到它的權利。但現在再添加一個數字到最後。

>> x = 1.23456789
x = 
      1.23456789

在其盛開,看X,如MATLAB看到它:

>> sprintf('%.60f',x) 
ans = 
1.23456789

所以時時提防任何浮點數的最後一位。 MATLAB會嘗試智能地對事物進行四捨五入,但是15位數字就在您安全的邊緣。

是否有必要使用像HPF或MP這樣的工具來解決這樣的問題?不,只要你認識到雙重限制。然而,提供任意精度的工具使您能夠在需要時更靈活。例如,HPF提供了在該地下室區域使用和控制警戒數字。如果你需要他們,他們會在那裏保存你需要的數字來防止腐敗。

+0

@niels - 但是,如果不使用可讓您以更高精度工作的工具,您無法達到要求的精度。儘管如此,您需要認識到使用浮點數字形式(這是雙倍數字形式)將始終使最不重要的數字處於危險之中。 HPF這種形式的另一個優點是它是十進制的。所以數字以十進制形式存儲,而不是二進制形式。 – 2012-06-06 09:09:32

+1

@niels - 是的,它完全是關於精度以及數字作爲二進制數存儲在雙精度數中的方式。在您明白0.280783054不能完全代表二進制浮點數的情況下,您將永遠無法解決此問題。 – 2012-06-06 09:38:59

+0

默認情況下,MATLAB將所有數字存儲爲double,因此尾數爲52個二進制位。如果您使用單個號碼來存儲號碼,那麼x =單號(0.280783054);你會得到:sprintf('%。30f',x) ans = 0.280783057212829589843750000000 – 2012-06-06 10:09:43

0

這是因爲你的數字超出了double數字類型的精度(它給你15到17個十進制數字)。在你的情況下,只要文字被評估,它就會四捨五入到最接近的可表示數字。

如果您需要比雙精度浮點提供的精度更高的精度,請將數字存儲在字符串中,或​​使用任意精度庫。例如使用符號工具箱:

sym('0.0111243254654764549999999') 
0

由於數字存儲在double類型或甚至long double類型中,因此無法獲得EXACT字符串。 存儲的號碼將比您提供的號碼多或少。

計算機只知道二進制數字0 & 1.您必須知道一個基數中的數字可能不會以其他基數表示。例如,數字1/3,基數10產生0.33333333 ...(省略號(三個點)表示仍然會有更多的數字出現,這裏是數字3),並且它將被截斷爲0.333333;基數3產生0.10000000,不多或少看到數量;基數2產生0.01010101 ...,所以它可能會截斷爲0.01010101在計算機中,這是85/256,舍入小於1/3,並且下一次您獲取數字,它將不會是您想要的相同

因此,從一開始,您應該將數字存儲在字符串中而不是浮點型,否則將失去精度。

考慮到精度問題,MATLAB爲任意精度提供了符號計算。