Как я могу преобразовать float / double в ASCII без использования sprintf или ftoa в C? - PullRequest
6 голосов
/ 15 февраля 2010

Как я могу преобразовать число с плавающей запятой / double в ASCII без использования sprintf или ftoa в C?

Я использую встроенную систему.

Ответы [ 3 ]

7 голосов
/ 15 февраля 2010

Подход, который вы выберете, будет зависеть от возможного диапазона значений.У вас наверняка есть некоторые внутренние знания о возможном диапазоне, и вас могут интересовать только преобразования в более узком диапазоне.

Итак, предположим, что вас интересует только целочисленное значение.В этом случае я бы просто присвоил число int или long, и в этот момент проблема становится достаточно очевидной.

Или предположим, что диапазон не будет включать в себя какие-либо большие показатели, но выинтересует несколько цифр дроби.Чтобы получить три цифры дроби, я мог бы сказать int x = f * 1000;, преобразовать x, а затем вставить десятичную точку как строковую операцию.

Если все вышеперечисленное не выполнено, число с плавающей запятой или двойное число имеет бит знака,дробь и показатель степени.Во фракции скрыт 1.(Числа нормализуются до тех пор, пока у них нет начальных нулей, после чего они делают еще один сдвиг, чтобы получить дополнительный бит точности.) Затем число равно дроби (плюс начальный «1») * 2 ** экспонента,Практически во всех системах, использующих представление IEEE 754, вы можете просто использовать эту страницу Википедии IEEE 754 , чтобы понять формат.Это не , что отличается от простого преобразования целого числа.

Для одинарной точности, как только вы получите экспоненту и дробь, значение Примечание 1 от числа равно (frac / 2 23 + 1) * 2 exp или frac * 2 exp - 23 + 2 exp .

Вот пример, который должен помочь вам начать полезное преобразование:

$ cat t.c
#include <stdio.h>

void xconvert(unsigned frac)
{
  if (frac) {
    xconvert(frac / 10);
    printf("%c", frac % 10 | '0');
  }
}

void convert(unsigned i)
{
  unsigned sign, exp, frac;

  sign = i >> 31;
  exp  = (i >> (31 - 8)) - 127;
  frac = i & 0x007fffff;
  if (sign)
    printf("-");
  xconvert(frac);
  printf(" * 2 ** %d + 2 ** %d\n", exp - 23, exp);
  printf("\n");
}

int main(void)
{
  union {
     float f;
     unsigned i;
  } u;

  u.f = 1.234e9;
  convert(u.i);
  return 0;
}
$ ./a.out
1252017 * 2 ** 7 + 2 ** 30

Примечание 1. В этом случае дробь преобразуется так, как если бы двоичная точка была навместо левого, с корректирующими корректировками, а затем с показателем степени и скрытого бита.

1 голос
/ 02 апреля 2012
#include<stdio.h>
void flot(char* p, float x)
{
  int n,i=0,k=0;
  n=(int)x;
  while(n>0)
  {
    x/=10;
    n=(int)x;
    i++;
 }
 *(p+i) = '.';
 x *= 10;
 n = (int)x;
 x = x-n;
 while((n>0)||(i>k))
 {
   if(k == i)
        k++;
   *(p+k)='0'+n;
   x *= 10;
   n = (int)x;
   x = x-n;
   k++;
 }
 /* Null-terminated string */
 *(p+k) = '\0';
}

int main()
{
  float x;
  char a[20]={};
  char* p=&a;
  printf("Enter the float value.");
  scanf("%f",&x);
  flot(p,x);
  printf("The value=%s",p);
  getchar();
  return 0;
}
0 голосов
/ 16 февраля 2010

Даже во встроенной системе вам будет сложно справиться с производительностью ftoa. Зачем изобретать велосипед?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...