#c #casting #floating-point #division
#c #Кастинг #с плавающей запятой #разделение
Вопрос:
Это часть присваивания, присвоение не связано с приведением, это то, что я пытаюсь сделать самостоятельно.
У меня возникли проблемы с приведением возвращаемого типа int к типу float в функции деления. Он продолжает возвращать 0, несмотря на наличие правильного значения в функции деления. Я прочитал кучу разных сообщений, касающихся соображений разделения int и округления в меньшую сторону, и я пытался реализовать множество различных решений, но безрезультатно.
У меня есть работоспособное решение для простой печати из функции, но я стараюсь оставаться последовательным во всей моей программе и обрабатывать возвращаемое значение.
Редактировать (ясность): функция divide имеет возвращаемый тип int, потому что я пытаюсь сохранить ее возвращаемый тип в соответствии с кучей других функций калькулятора, которые имеют возвращаемый тип int (в таблице отправки). Я пытаюсь выяснить, возможно ли вернуть дробную плавающую точку с помощью приведения из функции с возвращаемым типом int.
Вот соответствующий усеченный код для воспроизведения проблемы:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXARGS 15
#define min(a, b) ((a) < (b) ? (a) : (b))
struct argList {
int count;
char *args[MAXARGS];
} argList;
//Division function
int divide(int c, struct argList l){
float a = (strtol(l.args[0], NULL, 0));
float b = (strtol(l.args[1], NULL, 0));
printf("nIn Func = %fn", a/b);
return (float)(a/b);
}
int main(int argc, char **argv) {
int argCount = min(argc-1, MAXARGS);
int i = 0;
for (i = 0, argv ; i<argCount; i ) {
argList.args[i] = malloc(strlen(argv[i] 1));
strncpy(argList.args[i], argv[i], strlen(argv[i]) 1);
}
argList.count = i;
printf("Out of Func = %fn", (float)divide(argList.count, argList));
return 0;
}
Примеры выходных данных:
./main 2 5
In Func = 0.400000
Out of Func = 0.000000
./main 10 5
In Func = 2.000000
Out of Func = 2.000000
Тот факт, что второй ввод работает, заставляет меня поверить, что все еще существует проблема с целочисленным делением / округлением, о которой часто упоминается. Но я решил, что с приведением вызова функции и возвращаемого типа можно избежать этой проблемы.
Дайте мне знать, если у кого-нибудь есть какие-либо идеи по решению этой проблемы.
РЕДАКТИРОВАТЬ: попытки решения:
Приведение одного операнда, приведение обоих операндов, создание отдельной переменной, умножение на 100,0f, использование strtof
и strtod
вместо приведения к an strol
.
Комментарии:
1. Вы должны приводить операнды (достаточно одного), а не результат (который уже равен нулю)
2. Это не меняет результат. Я пробовал использовать один, оба, выполняя деление вне возвращаемого значения и возвращая отдельную переменную и т.д. Все тот же результат.
3. Потому что ваш
divide
int
по какой-то причине тоже возвращается.4. Правильно, я объяснил это в середине исходного сообщения. Я работаю с таблицей отправки функций из множества разных функций, все они имеют возвращаемый тип int, поэтому цель состоит в том, чтобы сохранить divide как возвращаемый тип int, но привести результирующее значение к типу float .
5. Тогда как вы ожидаете
int
, что функция вернет дробное число? Приведение приведет к уже усеченному результату, чего вы, похоже, не ожидаете.
Ответ №1:
Если вы приведете float к int, а затем к float. вероятно, вы никогда не получите исходное значение с плавающей точкой.
Что вам нужно, так это взять то, что присутствует в памяти, и рассматривать его как int . Для выполнения такого рода манипуляций вы используете объединение:
Например, вы добавляете:
typedef union {
float f;
int i;
} IF_t;
В функции divide вы заменяете печать и возврат на:
IF_t r;
r.f = a/b;
printf("nIn Func = %fn", r.f);
return r.i;
и вы заменяете printf в основном на:
res.i = divide(argList.count, argList);
printf("Out of Func = %fn", res.f);
конечно, вы объявляете IF_t res;
в main .
Ответ №2:
По крайней мере, эти проблемы:
Код находит длину некоторого аргумента. Эта ошибка позже приводит к неопределенному поведению (UB) в более позднем коде, поскольку выделяется недостаточно памяти.
// argList.args[i] = malloc(strlen(argv[i] 1));
argList.args[i] = malloc(strlen(argv[i]) 1);
Тогда зачем преобразовывать в целое float
число? Перейдите прямо к a float
.
// float a = (strtol(l.args[0], NULL, 0));
float a = strtod(l.args[0], NULL);
// or better
float a = strtof(l.args[0], NULL);
Комментарии:
1. Спасибо, первая часть является частью какого-то другого кода, над которым я работаю, я попытался просто включить то, что было уместно, чтобы проблема с возвращаемым типом была повторяемой. Я попробовал оба решения во второй части, и результат тот же.