Как языки справляются с плавающей печатью под капотом?

В качестве личного проекта я писал компилятор для моего собственного C-подобного языка, чтобы настроить эмулятор процессора моей собственной разработки.

В рамках этого я хочу реализовать стандартную библиотеку с плавающей запятой (типичная одинарная точность IEEE), но я изо всех сил пытался придумать способ распечатать числа с плавающей запятой в удобном для чтения виде (как в 1.2345, а не целое число исходных данных), лучшее, что я мог придумать, - это генерировать значения для log 10 2 и выполнять некоторые нечетные умножения, чтобы получить число в подходящей форме для печати.

Есть ли алгоритм для преобразования числа с плавающей запятой в легко печатаемую форму или для печати числа с плавающей запятой, который можно реализовать без использования printf("%f",float_value); или приведений типов на языке C?


person Xandros    schedule 16.05.2015    source источник
comment
Конечно, почему бы вам не взглянуть на реализацию printf?   -  person Oliver Charlesworth    schedule 16.05.2015
comment
Или один из них, например glibc, поскольку его исходный код доступен для загрузки.   -  person Iharob Al Asimi    schedule 16.05.2015
comment
возможный дубликат исходного кода функций c / c ++   -  person Ed Heal    schedule 16.05.2015
comment
Возможно, oldie, который делает наоборот, может помочь.   -  person Jongware    schedule 16.05.2015
comment
Зависит от того, какие правила вы сделаете для их печати (фиксированное количество десятичных знаков? Десятичное число, полностью эквивалентное по значению? Кратчайшая строка, для которой однозначно, какое число с плавающей запятой оно представляет?). Вы можете попробовать этот и многое сделать лучше, чем большинство текущих реализаций.   -  person harold    schedule 16.05.2015
comment
См. Классическую статью SIGPLAN «Как точно печатать числа с плавающей запятой» lists.nongnu.org/archive/html/gcl-devel/2012-10/   -  person Jerry101    schedule 16.05.2015
comment
См. netlib.org/fp/dtoa.c   -  person lhf    schedule 17.05.2015


Ответы (2)


Насколько я понимаю, в настоящее время в области печати чисел с плавающей запятой используется семейство алгоритмов Grisu Флориана Лойча. Вы можете прочитать статью здесь.

Для более легкого ознакомления с проблемами преобразования двоичной с плавающей запятой в десятичную (и наоборот) я настоятельно рекомендую сайт Рика Регана, http://www.exploringbinary.com/

person Simon Byrne    schedule 16.05.2015

Это может быть грязный взлом функции, но вы можете использовать это как основу для функции, которая будет правильно отображать числа с плавающей запятой. Он не использует никаких других вспомогательных функций, кроме putchar для фактического вывода чего-либо, и не охватывает все ситуации (например, ваш номер является NaN или даже отрицательным!), Но, ну, это всего лишь отправная точка. :

#include <stdio.h>

void printfloat (float n)
{
    int whole = n;
    int power = 1;
    int digit;

    /* Find out the largest divisor for printing the integer part */
    while (whole>=1)
    {
        whole /= 10;
        power *= 10;
    }
    power /= 10;

    /* Prints the integer part of the number */
    whole = n;
    while (power>=1)
    {
        digit = whole/power;
        whole %= power;
        putchar ('0'+digit);
        power /= 10;
    }

    /* Prints the decimal point */
    putchar ('.');

    /* And now the fractional part */
    n = n-(int)n;
    while(n!=0)
    {
        digit = n*10;
        putchar ('0'+digit);
        n*=10;
        n = n-(int)n;
    }
    putchar ('\n');
}

int main()
{
    float n = 123.45678;

    printfloat(n);
    return 0;
}

Вы можете проверить это здесь: http://goo.gl/V4pgNZ

person mcleod_ideafix    schedule 16.05.2015
comment
Нет, это нельзя использовать как основу для правильной работы. Это всего лишь грязный хакер, и чтобы перейти от него к чему-то, что работает правильно, нужно выбросить его. В свою защиту, чтобы реализовать правильное преобразование двоичного числа в десятичное в C с нуля, в основном необходимо начать с реализации хотя бы элементарной библиотеки bignum (openwall.com/lists/musl/2012/04/10/6), но если кто-то не хочет делать правильную версию, можно по адресу меньше всего делает opensource.apple.com/ источник / рубин / рубин-18 / рубин / отсутствует /. И прочтите explorebinary.com или couse. - person Pascal Cuoq; 17.05.2015