Специфікатор ширини Printf для підтримки точності значення з плаваючою комою


103

Чи існує printfспецифікатор ширини, який може бути застосований до специфікатора плаваючої точки, який автоматично відформатуватиме висновок на необхідну кількість значущих цифр, таким чином, що при скануванні рядка назад в ньому набувається початкове значення плаваючої точки?

Наприклад, припустимо, що я друкую a floatз точністю до 2десяткових знаків:

float foobar = 0.9375;
printf("%.2f", foobar);    // prints out 0.94

Коли я сканую вихід 0.94, у мене немає гарантії, що відповідає стандартам, що я 0.9375поверну оригінальне значення з плаваючою комою (у цьому прикладі я, мабуть, не стану).

Я хотів би сказати спосіб printfавтоматично надрукувати значення з плаваючою комою до необхідної кількості значущих цифр, щоб переконатися, що воно може бути відскановано до початкового значення, переданого до printf.

Я міг би використовувати деякі макроси, float.hщоб отримати максимальну ширину для передачі printf, але чи є вже специфікатор для автоматичного друку на необхідну кількість значущих цифр - або принаймні на максимальну ширину?


4
@bobobobo Ви просто рекомендуєте використовувати припущення з повітря, а не використовувати портативний підхід?

1
@ H2CO3 Ні, я б не рекомендував використовувати "припущення з повітря", я б запропонував використовувати printf( "%f", val );це вже портативне, ефективне та за замовчуванням.
bobobobo

2
@bobobobo Щоб я міг додати його до відповідей, чи зможете ви цитувати пункт у стандарті C99, який зазначає, що операція printf виводить тип float з максимальною точністю за замовчуванням, якщо не визначено точності?
Вільгельм Грей

1
@VilhelmGray Оскільки, як @chux потрапляє, існує досить складна математика щодо фактичної точності для вашої конкретної double. Оскільки ваш показник doubleстає надзвичайно великим (дуже далеко від 1,0), він фактично стає менш точним у десятковій частині (частка значення менше 1,0). Тож ви справді не можете отримати задовільну відповідь, оскільки у вашому запитанні є помилкове припущення (а саме, що всі floatс / doubleс створені рівними)
bobobobo

2
@Vilhelm Grey C11dr 5.2.4.2.2 "... число десяткових цифр, n, таким чином, що будь-яке число з плаваючою комою з цифрами p radix b може бути округлене до числа з плаваючою комою з n десятковими цифрами і назад знову без змін до значення, p log10 bb - потужність 10 ⎡1 + p log10 b⎤, інакше FLT_DECIMAL_DIG 6 DBL_DECIMAL_DIG 10 LDBL_DECIMAL_DIG 10 ... "6,10,10 - це мінімальні значення.
chux

Відповіді:


92

Я рекомендую @Jens Gustedt шістнадцятковий розчин: використовуйте% a.

ОП хоче «друкувати з максимальною точністю (або принаймні до найбільш значущої десяткової)».

Простим прикладом може бути друк однієї сьомої як у:

#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01

Але давайте копаємо глибше ...

Математично відповідь - "0,142857 142857 142857 ...", але ми використовуємо кінцеві точні числа з плаваючою комою. Припустимо, двійкові IEEE 754 з подвійною точністю . Тож OneSeventh = 1.0/7.0результати в наведеному нижче значенні. Також показані попередні та наступні представницькі doubleномери з плаваючою комою.

OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh        = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after  = 0.1428571428571428 769682682968777953647077083587646484375

Друк точного десяткового подання doubleобмеженого використання.

У C є 2 родини макросів, <float.h>щоб допомогти нам.
Перший набір - це кількість значущих цифр для друку в рядку десятковими, тому при скануванні рядка назад ми отримуємо оригінальну плаваючу крапку. Тут показано мінімальне значення специфікації C та компілятор вибірки С11.

FLT_DECIMAL_DIG   6,  9 (float)                           (C11)
DBL_DECIMAL_DIG  10, 17 (double)                          (C11)
LDBL_DECIMAL_DIG 10, 21 (long double)                     (C11)
DECIMAL_DIG      10, 21 (widest supported floating type)  (C99)

Другий набір - це кількість значущих цифр, рядки можуть бути скановані в плаваючу крапку, а потім надрукується FP, зберігаючи таку ж презентацію рядків. Тут показано мінімальне значення специфікації C та компілятор вибірки С11. Я вважаю, що доступний до C99.

FLT_DIG   6, 6 (float)
DBL_DIG  10, 15 (double)
LDBL_DIG 10, 18 (long double)

Перший набір макросів, схоже, відповідає цілі ОП - значущих цифр. Але цей макрос доступний не завжди.

#ifdef DBL_DECIMAL_DIG
  #define OP_DBL_Digs (DBL_DECIMAL_DIG)
#else  
  #ifdef DECIMAL_DIG
    #define OP_DBL_Digs (DECIMAL_DIG)
  #else  
    #define OP_DBL_Digs (DBL_DIG + 3)
  #endif
#endif

"+ 3" - це суть моєї попередньої відповіді. Його центр зосереджений на тому, що якщо ви знаєте зворотну конверсію string-FP-рядок (встановлено №2 макросів C89), як можна визначити цифри для FP-string-FP (встановити №1 макросів, доступних після C89)? Загалом, результат додав 3.

Тепер, скільки значущих цифр для друку відомо, і проходять через <float.h>.

Для друку N значущих десяткових цифр можна використовувати різні формати.

З "%e", поле точності - це кількість цифр після первинної цифри і десяткової крапки. Так - 1і в порядку. Примітка. Це -1не в початковійint Digs = DECIMAL_DIG;

printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01

З "%f", поле точності - це кількість цифр після десяткової крапки. Для такої кількості, як OneSeventh/1000000.0треба, потрібно було б OP_DBL_Digs + 6побачити всі суттєві цифри.

printf("%.*f\n", OP_DBL_Digs    , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285

Примітка. Багато хто звик "%f". На екрані відображається 6 цифр після коми; 6 - значення за замовчуванням на дисплеї, а не точність числа.


чому 1.428571428571428492127e-01, а не 1.428571428571428492127e-0 0 1, кількість цифр після 'e' має бути 3?
user1024

12.12.5 Перетворення з плаваючою комою говорить про точність за замовчуванням для %f6.
Jingguo Yao,

1
@Jingguo Яо Погоджуюся, що посилання говорить "Точність визначає, скільки цифр слідує за символом десяткової крапки для"% f "". Слово "точність" там не використовується в математичному сенсі, а просто для визначення кількості цифр після десяткової коми. 1234567890.123, математично має 13 цифр точності або значущих цифр. 0,000000000123 має 3 цифри математичної точності, а не 13. Числа з плаваючою комою є логарифмічно розподіленими. У цій відповіді використовуються значні цифри та математичний сенс точності .
chux

1
@Slipp Д. Томпсон "Показано мінімальне значення специфікації C та компілятор зразка C11".
chux

1
Дійсно, ви праві - мій трюк справедливий лише для значень з величиною від 1,0 до 1,0eDBL_DIG, що, мабуть, єдиний діапазон, який справді підходить для друку, "%f"в першу чергу. Використання, "%e"як ви показали, - це, звичайно, кращий підхід у цілому і ефективно гідний відповідь (хоча, можливо, це не так добре, як використання, "%a"якщо воно є, і, звичайно, "%a"повинно бути доступним, якщо `DBL_DECIMAL_DIG є). Я завжди хотів отримати специфікатор формату, який би завжди округлювався до максимальної точності (замість жорстко закодованих 6 знаків після коми).
Грег А. Вудс

66

Коротка відповідь на друк чисел з плаваючою комою без втрат (таких, щоб їх можна було прочитати з точнісінькою кількістю, за винятком NaN та нескінченності):

  • Якщо ваш тип float: використовуйте printf("%.9g", number).
  • Якщо ваш тип подвійний: використовуйте printf("%.17g", number).

НЕ використовуйте %f, оскільки це лише вказує, скільки значущих цифр після десяткових знаків і буде скорочувати невеликі числа. Для довідки можна знайти магічні числа 9 і 17, в float.hяких визначаються FLT_DECIMAL_DIGі DBL_DECIMAL_DIG.


6
Чи могли б ви пояснити %gспецифікатор?
Вільгельм Грей

14
% g друкує число з такою кількістю цифр, скільки потрібно для точності, віддаючи перевагу експоненціальному синтаксису, коли числа невеликі або величезні (1e-5, а не .00005) і пропускаючи будь-які проміжні нулі (1, а не 1.00000).
ccxvii

4
@truthseeker Для подання IEEE 754 бінарного коду дійсно потрібно надрукувати щонайменше 15 значних десяткових місць. Але однозначної необхідності необхідно 17, оскільки точність зміни двійкового числа (на 2,4,8 і т.д.) і десяткового числа (на 10 100,1000 і т.д.) ніколи не є однаковим числом (крім 1,0). Приклад: 2 doubleзначення трохи вище 0.1: 1.000_0000_0000_0000_2e-01, 1.000_0000_0000_0000_3e-01потреба 17 цифр , щоб відрізнити.
chux

3
@chux - Ви помиляєтесь щодо поведінки% .16g; це не є адекватним для вашого прикладу розрізнення 1.000_0000_0000_0000_2e-01 від 1.000_0000_0000_0000_3e-01. % .17 г потрібно.
Дон Хетч

1
@ Don Hatch Я погоджуюся "%.16g"недостатня "%.17g"і "%.16e"є достатньою. Подробиці %gмене запам'ятали неправильно.
chux

23

Якщо вас цікавить лише біт (resp hex pattern), ви можете використовувати %aформат. Це гарантує вам:

Точність за замовчуванням достатня для точного подання значення, якщо існує точне подання в базі 2 і в іншому випадку достатньо велике, щоб виділити значення типу подвійні.

Мені слід додати, що це доступно лише з C99.


16

Ні, немає такого специфікатора ширини printf, щоб друкувати з плаваючою комою з максимальною точністю . Дозвольте пояснити, чому.

Максимальна точність floatі doubleє змінною і залежить від фактичного значення з floatабо double.

Нагадаємо floatта doubleзберігаються у форматі sign.exponent.mantissa . Це означає, що для дробової складової використовується невелика кількість бітів для малих чисел, ніж для великих чисел.

введіть тут опис зображення

Наприклад, floatможна легко відрізнити 0,0 і 0,1.

float r = 0;
printf( "%.6f\n", r ) ; // 0.000000
r+=0.1 ;
printf( "%.6f\n", r ) ; // 0.100000

Але floatне має уявлення про різницю між 1e27та 1e27 + 0.1.

r = 1e27;
printf( "%.6f\n", r ) ; // 999999988484154753734934528.000000
r+=0.1 ;
printf( "%.6f\n", r ) ; // still 999999988484154753734934528.000000

Це пояснюється тим, що вся точність (яка обмежена кількістю бітів мантіси) використовується для більшої частини числа, що залишилася від десяткової.

%.fМодифікатор просто говорить , скільки десяткових значень ви хочете надрукувати з числа поплавка, наскільки форматування йде. Те, що наявна точність залежить від розміру номера, залежить від програміста . printfне може / не справляється з цим для вас.


2
Це відмінне пояснення обмежень точного друку значень з плаваючою комою на певних десяткових знаках. Однак я вважаю, що я був занадто неоднозначним зі своїм оригінальним вибором слів, тому я оновив своє запитання, щоб уникнути терміна "максимальна точність", сподіваючись, що це може усунути плутанину.
Вільгельм Грей

Це все ще залежить від значення номера, яке ви друкуєте.
bobobobo

3
частково це правда, але це не відповідає на запитання, і ви заплутані щодо того, що задає ОП. Він запитує, чи можна запитувати кількість значущих [десяткових] цифр подання float, і ви стверджуєте, що такого немає (тобто, що немає FLT_DIG), що неправильно.

@ H2CO3 Можливо, ви повинні відредагувати мою публікацію та зворотній зв'язок (j / k). Ця відповідь стверджує, FLT_DIGнічого не означає. Ця відповідь стверджує, що кількість доступних десяткових знаків залежить від значення всередині плавця .
bobobobo

1
Ви припускаєте, що лист формату має бути "f"? Я не думаю, що це потрібно. Моє читання цього питання є те , що OP шукає який - то формат Printf специфікатор , який виробляє , НЕ з втратами туди і назад, так @ccxvii «s відповіді ("% .9g "для поплавка,"% .17g "для подвійного) є хороший. Можливо, питання було б краще сформулювати, видаливши з нього слово "ширина".
Дон Хетч

11

Просто використовуйте макроси <float.h>та специфікатор перетворення змінної ширини ( ".*"):

float f = 3.14159265358979323846;
printf("%.*f\n", FLT_DIG, f);

2
@OliCharlesworth Ви маєте на увазі так:printf("%." FLT_DIG "f\n", f);
Вільгельм Грей

3
+1, але це найкраще працює %e, не дуже добре для %f: лише якщо відомо, що значення для друку близьке до 1.0.
Паскаль Куок

3
%eдрукує значні цифри для дуже малої кількості і %fне робить. напр x = 1e-100. %.5fвідбитки 0.00000(повна втрата прецесії). %.5eвідбитки 1.00000e-100.
chux

1
@bobobobo Також ви помиляєтесь, що це "дає більш точні причини". FLT_DIGвизначається значенням, яке воно визначено з причини. Якщо це 6, це тому float, що не може вмістити більше 6 цифр точності. Якщо ви друкуєте його за допомогою %.7f, остання цифра не матиме значення. Подумайте, перш ніж звернути увагу.

5
@bobobobo Ні, %.6fне рівнозначно, тому що FLT_DIGце не завжди 6. А хто дбає про ефективність? Введення / виведення вже дороге, як пекло, одна цифра з більшою або меншою точністю не зробить вузьке місце.

5

Я проведу невеликий експеримент, щоб переконатися, що друк із DBL_DECIMAL_DIGдійсно точно зберігає двійкове представлення числа. Виявилося, що для компіляторів і бібліотек С, які я спробував, DBL_DECIMAL_DIGсправді потрібна кількість цифр, а друк навіть на одну цифру менше створює значну проблему.

#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

union {
    short s[4];
    double d;
} u;

void
test(int digits)
{
    int i, j;
    char buff[40];
    double d2;
    int n, num_equal, bin_equal;

    srand(17);
    n = num_equal = bin_equal = 0;
    for (i = 0; i < 1000000; i++) {
        for (j = 0; j < 4; j++)
            u.s[j] = (rand() << 8) ^ rand();
        if (isnan(u.d))
            continue;
        n++;
        sprintf(buff, "%.*g", digits, u.d);
        sscanf(buff, "%lg", &d2);
        if (u.d == d2)
            num_equal++;
        if (memcmp(&u.d, &d2, sizeof(double)) == 0)
            bin_equal++;
    }
    printf("Tested %d values with %d digits: %d found numericaly equal, %d found binary equal\n", n, digits, num_equal, bin_equal);
}

int
main()
{
    test(DBL_DECIMAL_DIG);
    test(DBL_DECIMAL_DIG - 1);
    return 0;
}

Я запускаю це за допомогою компілятора Microsoft C 19.00.24215.1 та gcc версії 7.4.0 20170516 (Debian 6.3.0-18 + deb9u1). Використовуючи одну меншу десяткову цифру, вдвічі менше число чисел, що порівнюються рівно. (Я також переконався, що rand()при використанні насправді утворюється близько мільйона різних чисел.) Ось детальні результати.

Microsoft C

Тестовані значення 999507 з 17 цифрами: 999507 знайдено числово рівним, 999507 - двійковим рівним
Випробувано значення 999507 з 16 цифрами: 545389 знайдено числовим рівним, 545389 знайдено двійковим рівним

GCC

Випробувані значення 999485 з 17 цифрами: 999485 знайдено числово рівним, 999485 знайдено двійковим рівним
Випробувано значення 999485 з 16 цифрами: 545402 знайдено числово рівним, 545402 знайдено двійковим рівним

1
"запустити це за допомогою компілятора С на Microsoft" -> Цей компілятор може бути RAND_MAX == 32767. Розгляньте u.s[j] = (rand() << 8) ^ rand();або подібне, щоб певні всі біти отримали шанс бути 0 або 1.
chux - Відновіть Моніку

Дійсно, його RAND_MAX становить 32767, тому ваша пропозиція правильна.
Діомідіс Шпінеліс

1
Я оновив публікацію, щоб обробляти RAND_MAX, як запропонував @ chux-ReinstateMonica. Результати аналогічні отриманим раніше.
Діомідіс Шпінеліс

3

В одному зі своїх коментарів до відповіді я скаржився, що давно хотів певним чином роздрукувати всі значущі цифри у значенні з плаваючою комою у десятковій формі, майже так само, як і запитання. Ну я нарешті сів і написав це. Це не зовсім ідеально, і це демо-код, який друкує додаткову інформацію, але він здебільшого працює для моїх тестів. Будь ласка, дайте мені знати, чи бажаєте ви (тобто хтось) копію всієї програми обгортки, яка спрямовує її на тестування.

static unsigned int
ilog10(uintmax_t v);

/*
 * Note:  As presented this demo code prints a whole line including information
 * about how the form was arrived with, as well as in certain cases a couple of
 * interesting details about the number, such as the number of decimal places,
 * and possibley the magnitude of the value and the number of significant
 * digits.
 */
void
print_decimal(double d)
{
        size_t sigdig;
        int dplaces;
        double flintmax;

        /*
         * If we really want to see a plain decimal presentation with all of
         * the possible significant digits of precision for a floating point
         * number, then we must calculate the correct number of decimal places
         * to show with "%.*f" as follows.
         *
         * This is in lieu of always using either full on scientific notation
         * with "%e" (where the presentation is always in decimal format so we
         * can directly print the maximum number of significant digits
         * supported by the representation, taking into acount the one digit
         * represented by by the leading digit)
         *
         *        printf("%1.*e", DBL_DECIMAL_DIG - 1, d)
         *
         * or using the built-in human-friendly formatting with "%g" (where a
         * '*' parameter is used as the number of significant digits to print
         * and so we can just print exactly the maximum number supported by the
         * representation)
         *
         *         printf("%.*g", DBL_DECIMAL_DIG, d)
         *
         *
         * N.B.:  If we want the printed result to again survive a round-trip
         * conversion to binary and back, and to be rounded to a human-friendly
         * number, then we can only print DBL_DIG significant digits (instead
         * of the larger DBL_DECIMAL_DIG digits).
         *
         * Note:  "flintmax" here refers to the largest consecutive integer
         * that can be safely stored in a floating point variable without
         * losing precision.
         */
#ifdef PRINT_ROUND_TRIP_SAFE
# ifdef DBL_DIG
        sigdig = DBL_DIG;
# else
        sigdig = ilog10(uipow(FLT_RADIX, DBL_MANT_DIG - 1));
# endif
#else
# ifdef DBL_DECIMAL_DIG
        sigdig = DBL_DECIMAL_DIG;
# else
        sigdig = (size_t) lrint(ceil(DBL_MANT_DIG * log10((double) FLT_RADIX))) + 1;
# endif
#endif
        flintmax = pow((double) FLT_RADIX, (double) DBL_MANT_DIG); /* xxx use uipow() */
        if (d == 0.0) {
                printf("z = %.*s\n", (int) sigdig + 1, "0.000000000000000000000"); /* 21 */
        } else if (fabs(d) >= 0.1 &&
                   fabs(d) <= flintmax) {
                dplaces = (int) (sigdig - (size_t) lrint(ceil(log10(ceil(fabs(d))))));
                if (dplaces < 0) {
                        /* XXX this is likely never less than -1 */
                        /*
                         * XXX the last digit is not significant!!! XXX
                         *
                         * This should also be printed with sprintf() and edited...
                         */
                        printf("R = %.0f [%d too many significant digits!!!, zero decimal places]\n", d, abs(dplaces));
                } else if (dplaces == 0) {
                        /*
                         * The decimal fraction here is not significant and
                         * should always be zero  (XXX I've never seen this)
                         */
                        printf("R = %.0f [zero decimal places]\n", d);
                } else {
                        if (fabs(d) == 1.0) {
                                /*
                                 * This is a special case where the calculation
                                 * is off by one because log10(1.0) is 0, but
                                 * we still have the leading '1' whole digit to
                                 * count as a significant digit.
                                 */
#if 0
                                printf("ceil(1.0) = %f, log10(ceil(1.0)) = %f, ceil(log10(ceil(1.0))) = %f\n",
                                       ceil(fabs(d)), log10(ceil(fabs(d))), ceil(log10(ceil(fabs(d)))));
#endif
                                dplaces--;
                        }
                        /* this is really the "useful" range of %f */
                        printf("r = %.*f [%d decimal places]\n", dplaces, d, dplaces);
                }
        } else {
                if (fabs(d) < 1.0) {
                        int lz;

                        lz = abs((int) lrint(floor(log10(fabs(d)))));
                        /* i.e. add # of leading zeros to the precision */
                        dplaces = (int) sigdig - 1 + lz;
                        printf("f = %.*f [%d decimal places]\n", dplaces, d, dplaces);
                } else {                /* d > flintmax */
                        size_t n;
                        size_t i;
                        char *df;

                        /*
                         * hmmmm...  the easy way to suppress the "invalid",
                         * i.e. non-significant digits is to do a string
                         * replacement of all dgits after the first
                         * DBL_DECIMAL_DIG to convert them to zeros, and to
                         * round the least significant digit.
                         */
                        df = malloc((size_t) 1);
                        n = (size_t) snprintf(df, (size_t) 1, "%.1f", d);
                        n++;                /* for the NUL */
                        df = realloc(df, n);
                        (void) snprintf(df, n, "%.1f", d);
                        if ((n - 2) > sigdig) {
                                /*
                                 * XXX rounding the integer part here is "hard"
                                 * -- we would have to convert the digits up to
                                 * this point back into a binary format and
                                 * round that value appropriately in order to
                                 * do it correctly.
                                 */
                                if (df[sigdig] >= '5' && df[sigdig] <= '9') {
                                        if (df[sigdig - 1] == '9') {
                                                /*
                                                 * xxx fixing this is left as
                                                 * an exercise to the reader!
                                                 */
                                                printf("F = *** failed to round integer part at the least significant digit!!! ***\n");
                                                free(df);
                                                return;
                                        } else {
                                                df[sigdig - 1]++;
                                        }
                                }
                                for (i = sigdig; df[i] != '.'; i++) {
                                        df[i] = '0';
                                }
                        } else {
                                i = n - 1; /* less the NUL */
                                if (isnan(d) || isinf(d)) {
                                        sigdig = 0; /* "nan" or "inf" */
                                }
                        }
                        printf("F = %.*s. [0 decimal places, %lu digits, %lu digits significant]\n",
                               (int) i, df, (unsigned long int) i, (unsigned long int) sigdig);
                        free(df);
                }
        }

        return;
}


static unsigned int
msb(uintmax_t v)
{
        unsigned int mb = 0;

        while (v >>= 1) { /* unroll for more speed...  (see ilog2()) */
                mb++;
        }

        return mb;
}

static unsigned int
ilog10(uintmax_t v)
{
        unsigned int r;
        static unsigned long long int const PowersOf10[] =
                { 1LLU, 10LLU, 100LLU, 1000LLU, 10000LLU, 100000LLU, 1000000LLU,
                  10000000LLU, 100000000LLU, 1000000000LLU, 10000000000LLU,
                  100000000000LLU, 1000000000000LLU, 10000000000000LLU,
                  100000000000000LLU, 1000000000000000LLU, 10000000000000000LLU,
                  100000000000000000LLU, 1000000000000000000LLU,
                  10000000000000000000LLU };

        if (!v) {
                return ~0U;
        }
        /*
         * By the relationship "log10(v) = log2(v) / log2(10)", we need to
         * multiply "log2(v)" by "1 / log2(10)", which is approximately
         * 1233/4096, or (1233, followed by a right shift of 12).
         *
         * Finally, since the result is only an approximation that may be off
         * by one, the exact value is found by subtracting "v < PowersOf10[r]"
         * from the result.
         */
        r = ((msb(v) * 1233) >> 12) + 1;

        return r - (v < PowersOf10[r]);
}

Мені все одно, відповідає вона на питання чи ні - це дійсно вражає. Це потребувало певної думки, і його слід визнати та похвалити. Можливо, було б добре, якби ви якось включили (чи тут, чи ще) повний код для тестування, але навіть без цього це справді хороша робота. Майте +1 для цього!
Прифтан

0

Наскільки мені відомо, є добре дифундує алгоритм , що дозволяє висновок на необхідну кількість значущих цифр , наприклад , що при скануванні рядки назад, початкове значення з плаваючою точкою купуються в dtoa.cнаписаній Daniel Gay, який доступний тут на Netlib (див також пов'язаний папір ). Цей код використовується, наприклад, у Python, MySQL, Scilab та багатьох інших.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.