打开浮动到字符串 [英] Turn float into string
问题描述
我已经着手状态,当我需要把IEEE-754的单人和双人precision数字转换成字符串与基地 10
。有一个可用 FXTRACT
指令,但它仅提供指数和尾数为基地2个,为数字的计算公式是:
值=(-1)^ *号1(尾数)* 2 ^(指数偏置)
如果我有具体的一些基地的指令数,我就能够改变2 指数的基地 - 偏差的前pression一部分,但现在我不知道该怎么办。我也在想使用标准的圆形转化为整数,但它似乎是不可用的,因为它不提供precise转换。有谁知道什么是做它的方式/基本圣多美和普林西比?请帮忙。
我终于找到了另一种解决办法(这是在Java中)
{
/ *处理负无穷,正无穷大和NaN,返回如果'F'不是提到了一个* /
字符串RET =;
如果((保留= getSpecialFloats(F))。长度()!= 0)
返回RET;
}
INT NUM = Float.toRawIntBits(F);
INT指数=(int)的(((NUM>> 23)及为0xFF)-127); // 8位,偏置127
INT尾数= NUM&安培; 0x7FFFFF; // 23bits/ *商店小数指数* /
INT decimalExponent = 0;
用于计算/ *临时值* /
INT sideMultiplicator = 1;
为(;指数大于0; exponent--){
/ *在这个循环中,我计算指数的值。 MAX(无符号整数)= 2 ^ 32-1,而指数可在2 ^ 127 PR ST这样的* /
sideMultiplicator * = 2;
正因为如此/ *,如果sideMultiplicator的前两名位被设置,我们正在越来越接近溢出,我们需要一些值保存到decimalExponent * /
如果((sideMultiplicator>>!30)= 0){
decimalExponent + = 3;
sideMultiplicator / = 1000;
}
}
为(;指数℃,;指数++){
/ *这个循环不正是相同的事情在循环之前,但反之亦然(对于指数℃下,如2 ^ -3等)* /
如果((sideMultiplicator&放大器;!1)= 0){
sideMultiplicator * = 10;
decimalExponent--;
}
sideMultiplicator / = 2;
}/ *我们知道,浮动值为:
* 1.mantissa * 2 ^指数*(-1)^符号* /
/ *这就是为什么我们需要存储1 betweenResult(另一temorary值)* /
INT betweenResult = sideMultiplicator;
对于(INT分数= 2位= 0;比特LT; 23;位++,部分* = 2){
/ *这个循环是最重要的:它通过把我们的指数变成了二进制尾数真正的价值* /
如果(((尾数>>(22位))及1)== 1){
/ *如果尾数[位]时,我们需要分数来划分整数(分数为2 ^(位+ 1))* /
而(sideMultiplicator%分数大于0&放大器;及(betweenResult>> 28)== 0){
/ *因为我们需要它之前:如果数字变近溢出,在decimalExponent店里的东西* /
betweenResult * = 10;
sideMultiplicator * = 10;
decimalExponent--;
}
betweenResult + = sideMultiplicator /分;
}
}/ *小转向正常化像15700号码betweenResult成157e2(存储decimalExponent变量零填充)* /
而(betweenResult%10 == 0){
betweenResult / = 10;
decimalExponent ++;
}
/ *这个方法(按十年或只是正常的科学,乘法)得到的字符串中reqested记号* /
返回getExponentedString(betweenResult,decimalExponent);
格式化浮点数是相当不平凡。例如搜索对于Dragon4算法(<一个href=\"http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/\"相对=nofollow>这里是一个结果)。
非常的非常的天真,你可以试试这个:
-
柄楠无限。
-
打印符号(检查
℃的
)。假设今后数为正实。 -
如果
&GT; = 1
,截断和使用熟悉的整数格式打印的组成部分。 (应该有上具有浮点单元的硬件机器指令。) -
打印小数点分隔符;现在继续乘以10和打印截断的整体数字。
-
当你已经达到了预期precision停止;想想正确舍入最后一位。
I have proceeded to state when I need to turn IEEE-754 single and double precision numbers into strings with base 10
. There is FXTRACT
instruction available, but it provides only exponent and mantissa for base 2, as the number calculation formula is:
value = (-1)^sign * 1.(mantissa) * 2^(exponent-bias)
If I had some logarithmic instructions for specific bases, I would be able to change base of 2exponent - bias part in expression, but currently I don't know what to do. I was also thinking of using standard rounded conversion into integer, but it seems to be unusable as it doesn't offer precise conversion. Does anybody know what is the way/basic principe for doing it? Please help.
I finally found another solution (it's in 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);
Formatting a floating point number is rather non-trivial. Search e.g. for the Dragon4 algorithm (here is one result).
Very, very naively, you could try this:
Handle NaN and Infinity.
Print the sign (check
< 0
). Assume henceforth the number is positive real.If
>= 1
, truncate and use familiar integer formatting to print the integral part. (There should be a machine instruction for that on any hardware that has a floating point unit.)Print the decimal separator; now keep multiplying by 10 and print the truncated integral digit.
Stop when you've reached the desired precision; think about rounding the last digit correctly.
这篇关于打开浮动到字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!