Как бы я вывел целое число из числа с плавающей точкой в ​​смысле удаления десятичной точки, несмотря на ошибки точности с плавающей точкой? - PullRequest
0 голосов
/ 28 февраля 2020

В C, как я могу произвести, например, 314159 из 3.14159 или 11 из 1.1 поплавков? Я не могу использовать #include вообще, и мне не разрешено использовать библиотечные функции. Он должен быть полностью кросс-платформенным и соответствовать одной функции.

Я пробовал это:

while (Number-(int)Number) {
    Number *= 10;
}

и это:

Number *= 10e6;

и точность с плавающей точкой ошибки мешают мне. Как я могу это сделать? Как я могу точно преобразовать все цифры в float в целое число? В ответ на комментарий они являются float аргументом функции:

char *FloatToString(char *Dest, float Number, register unsigned char Base) {
    if (Base < 2 || Base > 36 || !Dest) {
        return (char *)0;
    }
    char *const RDest = Dest;
    if (Number < 0) {
        Number = -Number;
        *Dest = '-';
        Dest++;
    }
    register unsigned char WholeDigits = 1;
    for (register unsigned int T = (int)Number/Base; T; T /= Base) {
        WholeDigits++;
    }
    Dest[WholeDigits] = '.';
    // I need to now effectively "delete" the decimal point to further process it. Don't answer how to convert a float to a string, answer the title.
    return RDest;
}

Ответы [ 4 ]

1 голос
/ 28 февраля 2020

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

Если вам не нужно беспокоиться о большие числа, вы можете сделать это проще всего, преобразовав в long:

v = v - (long)v;   // remove the integer part
int frac = (int)(v * 100000);

даст вам 5 цифр после десятичной точки. Проблема в том, что он дает неопределенное поведение, если начальное значение слишком велико для преобразования в long. Возможно, вы также захотите округлить по-другому (преобразовать в усечения int до нуля) - если вам нужно ближайшее значение, а не первые 5 цифр дроби, вы можете использовать (int)(v * 100000 + (v > 0 ? 0.5 : -0.5))

0 голосов
/ 28 февраля 2020

Новая версия:

#include <stdio.h>

int main()
{
    double x;
    int i;
    char s[10];
    x = 9999.12504;
    x = (x-(int)x);
    sprintf(s,"%0.5g\n",x);
    sscanf((s+2),"%d",&i);


    printf("%d",i);
    return 0;
}

Старая версия

#include <stdio.h>

    int main()
    {
        float x;
        int i;
        x = -3.14159;
        x = (x-(int)x);
        if (x>=0)
            i = 100000*x;
        else
            i = -100000*x;

        printf("%d",i);
        return 0;
    }
0 голосов
/ 28 февраля 2020
#include <stdio.h>
#include <stdint.h>
#include <limits.h>

int main(void) {
    double t = 0.12;
    unsigned long x = 0;

    t = (t<0)? -t : t;  // To handle negative numbers.
    for(t = t-(int)t; x < ULONG_MAX/10; t = 10*t-(int)(10*t))
    {
        x = 10*x+(int)(10*t);
    }

    printf("%lu\n", x);
    return 0;
}

Выход:

11999999999999999644
0 голосов
/ 28 февраля 2020

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

...