Я пытаюсь написать функцию на 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 оставляет множество возможностей для оптимизации кода и достижения высокой производительности приложений.
%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