0

當我需要將基於10的IEEE-754單精度和雙精度數字轉換爲字符串時,我已進入狀態。有FXTRACT指令可用,但它僅提供指數和尾數爲基數2,如數量,計算公式爲:將浮動字符串轉換爲字符串

value = (-1)^sign * 1.(mantissa) * 2^(exponent-bias) 

如果我有特定的鹼基一些對數的說明,我將能夠改變的2基地指數 - 偏差部分表達,但目前我不知道該怎麼辦。我也在考慮使用標準的四捨五入轉換爲整數,但它似乎無法使用,因爲它不提供精確的轉換。有沒有人知道這樣做的基本原理是什麼?請幫忙。

我終於找到了另一種解決方案(這是在Java中)

{ 
    /* handling -infinity, +infinity and NaN, returns "" if 'f' isn't one of mentioned */ 
    String ret = ""; 
    if ((ret = getSpecialFloats(f)).length() != 0) 
     return ret; 
} 
int num = Float.toRawIntBits(f); 
int exponent = (int)(((num >> 23) & 0xFF)-127); //8bits, bias 127 
int mantissa = num & 0x7FFFFF; //23bits 

/* stores decimal exponent */ 
int decimalExponent = 0; 
/* temporary value used for calculations */ 
int sideMultiplicator = 1; 
for (; exponent > 0; exponent--) { 
    /* In this loop I'm calculating the value of exponent. MAX(unsigned int) = 2^32-1, while exponent can be 2^127 pr st like that */ 
    sideMultiplicator *= 2; 
    /* because of this, if top two bits of sideMultiplicator are set, we're getting closer to overflow and we need to save some value into decimalExponent*/ 
    if ((sideMultiplicator >> 30) != 0) { 
     decimalExponent += 3; 
     sideMultiplicator /= 1000; 
    } 
} 
for(; exponent < 0; exponent++) { 
    /* this loop does exactly same thing as the loop before, but vice versa (for exponent < 0, like 2^-3 and so on) */ 
    if ((sideMultiplicator & 1) != 0) { 
     sideMultiplicator *= 10; 
     decimalExponent--; 
    } 
    sideMultiplicator /= 2; 
} 

/* we know that value of float is: 
* 1.mantissa * 2^exponent * (-1)^sign */ 
/* that's why we need to store 1 in betweenResult (another temorary value) */ 
int betweenResult = sideMultiplicator; 
for (int fraction = 2, bit = 0; bit < 23; bit++, fraction *= 2) { 
    /* this loop is the most important one: it turns binary mantissa to real value by dividing what we got in exponent */ 
    if (((mantissa >> (22-bit)) & 1) == 1) { 
     /* if mantissa[bit] is set, we need to divide whole number by fraction (fraction is 2^(bit+1)) */ 
     while (sideMultiplicator % fraction > 0 && (betweenResult >> 28) == 0) { 
      /* as we needed it before: if number gets near to overflow, store something in decimalExponent*/ 
      betweenResult *= 10; 
      sideMultiplicator *= 10; 
      decimalExponent--; 
     } 
     betweenResult += sideMultiplicator/fraction; 
    } 
} 

/* small normalization turning numbers like 15700 in betweenResult into 157e2 (storing zero padding in decimalExponent variable)*/ 
while (betweenResult % 10 == 0) { 
    betweenResult /= 10; 
    decimalExponent++; 
} 
/* this method gets string in reqested notation (scientific, multiplication by ten or just normal)*/ 
return getExponentedString(betweenResult, decimalExponent); 
+1

爲什麼不鏈接到標準C庫並調用'printf'或'sprintf'? –

+0

http://stackoverflow.com/questions/22962040/easiest-way-to-convert-a-decimal-float-to-bit-representation-manually-based-on-i和http:// stackoverflow的副本。com/questions/23540139/how-to-convert-floating-point-number-to-ieee-754-using-assembly –

+0

這很難做到這一點,並且@PascalCuoq已經寫了一個[blog](http: /www.exploringbinary.com/correct-decimal-to-floating-point-using-big-integers/)關於此 –

回答

3

格式化浮點數是相當不重要的。搜索例如對於Dragon4算法(here is one result)。

非常,非常天真,你可以試試這個:

  1. 柄楠無限。

  2. 打印標誌(檢查< 0)。以後假設這個數字是正實數。

  3. 如果是>= 1,則截斷並使用熟悉的整數格式打印整數部分。 (在任何具有浮點單元的硬件上應該有機器指令)

  4. 打印小數分隔符;現在保持乘以10並打印截斷的整數數字。

  5. 當您達到所需的精度時停止;考慮正確舍入最後一位數字。

+0

非常感謝。順便說一句,那'非常'呢?如果這將是'非常'緩慢的方式? – user35443

+0

@ user35443:因爲我沒有考慮效率,所以我鞭打了這個,我想這會非常慢。我認爲Dragon4與當時的文獻庫相比是快速的。我不知道任何細節,但是想象一下,我的想法被10 *分成很多*,這是一個相當慢的計算。 –

1

如果可以接受打印爲1.d1d2d3d4d5 ... * 2^e1e2e3,然後轉換浮點數爲十進制( - ish)表示可以很簡單。一個實現可以被發現here

如果您需要一個科學的1.d1d2 ... * 10^e1e2e3表示法,那麼您可以使用天真的方法重複除以10,並從浮點格式中提取數字。您將需要某種多精度整數庫。 (重複乘以10以提取點後的數字。)

+0

我不熟悉該語言,但仍感謝您的幫助。我想我會選擇一種天真的方式。 – user35443

0

Kerrek SB的解決方案是正確的。但是你可以更快地完成任何循環。只需以10 ^精度乘以小數部分即可。 例如,要將0.1234567轉換爲5位數的精度,請將數字乘以10000並獲得int部分。如果需要四捨五入,請將其乘以100000並舍入最後一個數字

+0

這種方法在人們不關心精確倒圓的情況下,也不關心類型極限附近的精度時快速簡單。我建議最後一步通常可以簡化爲乘以200000,轉換爲整數,加1,再除以2。請注意,請注意,在不同情況下,數字可能會有所不同。 Turbo C 2.00有一個錯誤,其中'printf(「%1.2f」,99.999999996);'會確定小數點左邊有兩位數字,將該值轉換爲一個字符串(「100.00」),然後。 .. – supercat

+0

...打印小數點左邊兩位數字(即「00.00」)的結果。哎呀。儘管如此,你的方法可以確保即使它不總是產生精確的值,它們也不可能是Just Plain Wrong。 – supercat

+0

我終於找到了另一個解決方案,編輯我的文章。 – user35443