Как разделить два длинных двойных числа в C?

Я пытаюсь написать функцию на C, которая обрабатывает long в строку, которая имеет long в качестве единицы хранения (например, 1400000 -> 1,40 МБ). Однако числа, которые он выводит, смешны, например, 4096 байт становятся 4233576455 КБ вместо 4,09 КБ. Я пробовал много исправлений, таких как приведение делителя и дивиденда и изменение формата в sprintf. Вот МРЭ:

#include <malloc.h>
#include <math.h>

long double rround(long double in,int places) {
    long double ir = in * pow(10,places);
    return roundl(ir) / pow(10,places);
}

char* parse_size(long indata) {
    char* final = (char*)malloc(30);
    if (indata < 0) {
        indata = -indata;
    }
    indata = (long double)indata;//Force long double over long with no floating point
    if (indata > (long double)2000000000) {
        sprintf(final,"%lld GB",rround(indata/1000000000.0,2));
    } else if (indata > (long double)2000000) {
        sprintf(final,"%lld MB",rround(indata/1000000.0,2));
    } else if (indata > (long double)2000) {
        sprintf(final,"%lld KB",rround(indata/1000.0,2));
    } else {
        sprintf(final,"%lld bytes",rround(indata,2));
    }

    return final;
}
int main() {
    long bytes = 4096;
    printf("Expected: 4.09 KB\n");
    printf("Actual: %s\n",parse_size(bytes));
}

Если вы запустите эту программу здесь, вы получите этот вывод

Expected: 4.09 KB
Actual: 4233576455 KB

🤔 А знаете ли вы, что...
C оставляет множество возможностей для оптимизации кода и достижения высокой производительности приложений.


1
65
2

Ответы:

Решено

%lld утверждает, что вы пройдете long long int; вы передаете long double, поэтому вы печатаете мусор (в лучшем случае он будет пытаться напечатать некоторые биты, представляющие long double, как если бы они представляли long long; во многих системах это будет чтение из совершенно не связанного регистра, который не имеет t даже не был инициализирован чем-то конкретным, и вы получите полный мусор). Вам нужен код формата %Lf или %.2Lf, чтобы ограничиться двумя цифрами после запятой.



char* parse_size(long long indata) {
    char* final = (char*)malloc(30);

    long double indataLD = (long double)abs(indata);
    if (indata > 2000000000) {
        sprintf(final,"%.2Lf GB",(indataLD/1000000000.0));
    } else if (indata > 2000000) {
        sprintf(final,"%.2Lf MB",(indataLD/1000000.0));
    } else if (indata > 2000) {
        sprintf(final,"%.2Lf KB",(indataLD/1000.0));
    } else {
        sprint(final,"%.2Lf Bytes",indataLD);
    }

    return final;
}

int main() {
    long long bytes = 4096;
    printf("Expected: 4.09 KB\n");
    printf("Actual: %s\n",parse_size(bytes));
}

Это дает

c++ version is 201703
g++ 8.1.0
Expected: 4.09 KB
Actual: 4.10 KB