Как напечатать значение с плавающей точкой, используя putchar? - PullRequest
3 голосов
/ 05 декабря 2010

Я работаю над встроенным приложением и мне нужно напечатать значения с плавающей запятой. Из-за нехватки места и других ограничений я могу использовать только putchar () для вывода.

Я пытаюсь создать функцию, которая принимает float в качестве параметра и печатает его, используя putchar (). У меня есть аналогичная функция, которая работает для целочисленных значений.

void putLong(long x)
{
    if(x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x >= 10) 
    {
        putLong(x / 10);
    }
    putchar(x % 10+'0');
}

Как сделать подобную функцию для поплавков?

Ответы [ 3 ]

2 голосов
/ 06 декабря 2010

Вот возможное решение:

typedef enum
{
    DEC1 = 10,
    DEC2 = 100,
    DEC3 = 1000,
    DEC4 = 10000,
    DEC5 = 100000,
    DEC6 = 1000000,

} tPrecision ;

void putFloat( float f, tPrecision p )
{
    long i = (long)f ;
    putLong( i ) ;
    f = (f - i) * p ;
    i = abs((long)f) ;
    if( fabs(f) - i >= 0.5f )
    {
        i++ ;
    }
    putchar('.') ;
    putLong( i ) ;
    putchar('\n') ;
}

Вы бы использовали это так:

putFloat( 3.14159f, DEC3 ) ;

, который выведет «3.142», обратите внимание на округление до третьей цифры.

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

При использовании этой функции вы должны знать, что число с плавающей точкой имеет только 6 значащих цифр точности, а не шесть десятичных знаков . Поэтому, если вы попытаетесь напечатать, скажем, 123.456, используя DEC6, вы получите ошибочные цифры после третьего места. Любые цифры после 6-й значащей цифры следует игнорировать, но написание кода для учета этого может быть ненужным в вашем приложении или более дорогим, чем вы хотели бы, учитывая ваши ограничения.

1 голос
/ 05 декабря 2010

Какой диапазон значений и требований к точности / точности вам нужен? Печать точного значения числа с плавающей запятой в десятичном виде является очень сложной проблемой и требует до 8 КБ или около того (у меня может быть несколько степеней 2; это не в моей голове) рабочего пространства, если вы поддержка 80-битных или 128-битных long double значений. Вы, вероятно, можете обойтись с 1 кб или около того, если вы поддерживаете только double, и, по сути, не имеете рабочего пространства, если вы просто хотите печатать плохие приближения.

ОК, так вот действительно базовая версия:

void putDouble(double x, int p)
{
    long d;
    if (x<0) {
        putchar('-');
        x=-x;
    }
    d = x;
    putLong(d);
    putchar('.');
    while (p--) {
        x = (x - d) * 10;
        d = x;
        putchar('0'+d);
    }
}

Возможно, вы захотите исправить putLong для обработки чисел длиннее 2 цифр, 2.: -)

0 голосов
/ 05 декабря 2010

Я думаю, что мой основной подход заключается в том, чтобы отделить целую часть значения с плавающей запятой от десятичной части.

Если вы можете использовать какое-либо округление или преобразование в целочисленную функцию, вы можете использовать метод putLongвам уже нужно вывести целочисленную часть.

Вывести десятичную точку.

Затем вычтите это int из числа с плавающей запятой, чтобы выделить десятичную дробь.Теперь для десятичной дроби вы можете либо попытаться определить количество мест после десятичной дроби, либо просто умножить на произвольно большую степень 10, затем удалить лишние нули с правой стороны полученного целого и снова применить putLongдля результата.

Я подозреваю, что может быть более эффективный или более простой способ сделать это, но я почти уверен, что этот подход будет работать.Также может быть полезно посмотреть, как биты с плавающей точкой используются для представления компонентов степени и значения.

...