confundido
confundido

Reputation: 64

Issues with division: casting an int return type to float, returning 0

This is part of an assignment, the assignment is unrelated to the casting, its something I'm trying to do on my own.

I'm having issues with casting an int return type to a float in a division function. It keeps returning 0, despite having the correct value in the division function. I have read a bunch of different posts regarding int division considerations and rounding down, and I have tried implementing a variety of different solutions to no avail.

I have a workable solution to just print from within the function, but I'm trying to stay consistent throughout my program and deal with the returned value.

Edit (clarity): The divide function has a return type int because I'm trying to keep its return type consistent with a bunch of other calculator functions that have return type int (in a dispatch table). I'm trying to see if its possible to return a fractional floating point, via casting, from a function with an int return type.

Here is the relevant truncated code to reproduce the problem:

#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 = %f\n", 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 = %f\n", (float)divide(argList.count, argList));
  
  return 0;
}

Sample outputs:

./main 2 5

In Func = 0.400000
Out of Func = 0.000000


./main 10 5

In Func = 2.000000
Out of Func = 2.000000

The fact that the second input works leads me to believe its still a problem with the integer division/rounding that is frequently mentioned. But I figured with the casting of the function call and return type that it would avoid that issue.

Let me know if anyone has any ideas to resolve this issue.

EDIT: Attempted solutions:

Casting one operand, casting both operands, creating a separate variable, multiplying by 100.0f, using strtof and strtod instead of casting to an strol.

Upvotes: 0

Views: 492

Answers (2)

yflelion
yflelion

Reputation: 1746

If you cast a float to int and then to a float. you will probably never get the original float.

What you need is to take what is present in the memory and consider it as an int. To do this kind of manipulation you use an union:

For example You add:

typedef union {
  float f;
  int   i;
} IF_t;

In divide function you replace the print and the return by:

IF_t r;
r.f = a/b;
printf("\nIn Func = %f\n", r.f);
return r.i;

and you replace the printf in the main by:

res.i = divide(argList.count, argList);
printf("Out of Func = %f\n", res.f);

of course you declare IF_t res; in the main.

Upvotes: 1

chux
chux

Reputation: 153303

At least these problem:

Code is finding the length of some of the argument. This error later leads to undefined behavior (UB) in later code as insufficient memory is allocated.

// argList.args[i] = malloc(strlen(argv[i]+1));
argList.args[i] = malloc(strlen(argv[i]) + 1);

Why convert to an integer, then float? Go right to 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);

Upvotes: 1

Related Questions