Как разделить два длинных двойных числа в 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
indata = (long double)indata; может только потерять данные (когда long больше битов, чем long double может представить в целочисленном смысле), потому что вы назначаете его обратно indata, который является long. В этой строке полная фигня. И %lld для печати long long int, а не long double.
ShadowRanger 22.02.2023 03:59
%lld — это спецификатор формата для long long int. Ваша функция возвращает длинный двойной...
Shawn 22.02.2023 03:59
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
1
2
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Спасибо, но сейчас печатается Actual: 0.000000 KB

Enderbyte09 22.02.2023 04:02

@ Enderbyte09: У меня отлично работает. Попробуйте онлайн! Печатает 4.10, а не 4.09, но 4.10 все равно правильнее.

ShadowRanger 22.02.2023 04:04

Большое спасибо! Я поставил %lf вместо %Lf

Enderbyte09 22.02.2023 04:07

@ Enderbyte09: Да, правила довольно строгие, и в них нет четкой рифмы или причины (обычно это исторический крафт, который заставляет такие вещи). Вам просто нужно проверить таблицы спецификаторов преобразования и модификаторов длины.

ShadowRanger 22.02.2023 04:09

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

Другие вопросы по теме