Проблемы с разделением: преобразование возвращаемого типа int в float, возврат 0

#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. Спасибо, первая часть является частью какого-то другого кода, над которым я работаю, я попытался просто включить то, что было уместно, чтобы проблема с возвращаемым типом была повторяемой. Я попробовал оба решения во второй части, и результат тот же.