0

I'm wondering if I'm using the correct variable types or not. I'm supposed to use only floats and ints as far as I'm aware. I know its printing the "divide by 4" part because in the function I switched it to divide by 5 and it printed "5.0000". If I make "result" an int, it obviously strips the answer of the decimal points, but it still gives me the correct average and not "4". Why is it storing "4.0000" in the result variable instead of the answer?

void main(void)
{
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;
// stop watchdog timer\

srand(time(NULL));
int val1 = (rand()%100);
int val2 = (rand()%100);
int val3 = (rand()%100);
int val4 = (rand()%100);
printf("%d\n",val1);
printf("%d\n",val2);
printf("%d\n",val3);
printf("%d\n",val4);

printf("%f\n",average4(val1, val2, val3, val4));
}


float average4(int val1, int val2, int val3, int val4){
float result;
result = (val1 + val2 + val3 + val4)/4;
return result;
}
  • Oh you know what this might be the solution. I can't do it at the moment but no I do not have that prototype. – Bartosz Karaban Jan 24 '18 at 16:21
  • 3
    Possible duplicate of [How can I force division to be floating point? Division keeps rounding down to 0](https://stackoverflow.com/questions/1267869/how-can-i-force-division-to-be-floating-point-division-keeps-rounding-down-to-0) – phuclv Jan 24 '18 at 16:39
  • 2
    Compiler warnings, enable them, look at them. – n. m. could be an AI Jan 24 '18 at 16:57
  • the signature for the function `main()` always has the return type `int`, (regardless of what visual studio allows) – user3629249 Jan 24 '18 at 17:09
  • the posted code does not compile! Amongst other things, the necessary header file(s) are not included. – user3629249 Jan 24 '18 at 17:10
  • for ease of readability and understanding: 1) consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces. – user3629249 Jan 24 '18 at 17:18
  • When compiling, always enable the warnings, then fix those warnings. (for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) – user3629249 Jan 24 '18 at 17:19

2 Answers2

1

Two issues:

  1. (val1 + val2 + val3 + val4)/4; is computed in integer arithmetic, as the terms are integral types. The remainder is discarded.

    One fix is to write 1.f * (val1 + val2 + val3 + val4) / 4; or the slightly obfuscated 0.25f * (val1 + val2 + val3 + val4);

  2. You're missing a prototype for average4. Formally the behaviour on doing that is undefined (since and including C99), you might be observing a conversion to int at the calling site.

Community
  • 1
  • 1
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    I think `1f` would be a syntax error. At least on some compilers I used the `f` suffix is still requiring a decimal point. – Eugene Sh. Jan 24 '18 at 16:16
  • @EugeneSh: I wonder what the C standard says: let's wait for some downvotes. – Bathsheba Jan 24 '18 at 16:16
  • @EugeneSh.: Would be worth it if this answer is incorrect. I'll check for sure later. – Bathsheba Jan 24 '18 at 16:17
  • So why does it give me the answer "4.0000" instead of stripping the answer of its decimal values? – Bartosz Karaban Jan 24 '18 at 16:18
  • @BartoszKaraban: because it assigns that integral type to a `float`. – Bathsheba Jan 24 '18 at 16:19
  • @Bathsheba http://port70.net/~nsz/c/c11/n1570.html#6.4.4.2 If I read the BNF properly, it is required as part of `floating-constant <- decimal-floating-constant <- fractional-constant <- digit-sequence .` – Eugene Sh. Jan 24 '18 at 16:20
  • @EugeneSh.: Yes, I concur. Thank you. – Bathsheba Jan 24 '18 at 16:22
  • 1
    I assume the not so obfuscated `(val1 + val2 + val3 + val4) / 4.0f` would do too. – Rudy Velthuis Jan 24 '18 at 18:39
  • @RudyVelthuis I dislike putting the float term at the end due to expressions being grouped from left to right. e.g. 3 / 5 * 3.0 is zero. – Bathsheba Jan 24 '18 at 18:49
  • @Bathsheba: but `int / float`returns a `float`. The expression (plain addition) in parentheses is an `int`, indeed, but it is being divided by a `float`. So in this case, there is no problem. – Rudy Velthuis Jan 24 '18 at 19:09
  • @RudyVelthuis: Indeed but it is vulnerable to errant refactoring or the introduction of extra coefficients on the left. – Bathsheba Jan 24 '18 at 19:15
  • @Bathsheba: Only if a division is entered. Not very vulnerable, IMO. – Rudy Velthuis Jan 24 '18 at 19:31
  • @RudyVelthuis: My team have fallen for it. The remedy is simple: promote the first term, pretty please, with sugar on top? – Bathsheba Jan 24 '18 at 19:41
  • @Bathsheba: Whatever you like. But it would be less obfuscated and valid, right? Now, how you or your team handle such problems is up to you. I would not worry too much about it. – Rudy Velthuis Jan 24 '18 at 19:45
1

the following proposed code:

  1. doesn't quite compile because the three fields: WDT_A WDT_A_CTL_HOLD and WDT_A_CTL_PW are not declared.

And now the proposed code, with commentary

#include <stdio.h>     // printf()
#include <stdlib.h>    // rand(), srand()
#include <time.h>      // time()

// prototypes
float average4(int val1, int val2, int val3, int val4);


int main(void)                       // corrected signature
{
    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;
    // stop watchdog timer           // removed trailing line continuation 'slash'

    srand( (unsigned int)time(NULL)); // cast to expected type
    int val1 = (rand()%100);
    int val2 = (rand()%100);
    int val3 = (rand()%100);
    int val4 = (rand()%100);
    printf("%d\n",val1);
    printf("%d\n",val2);
    printf("%d\n",val3);
    printf("%d\n",val4);

    printf("%f\n",average4(val1, val2, val3, val4));
}


float average4(int val1, int val2, int val3, int val4)
{
    float result;
    // cast the 'integer' sum to 'float',
    // properly declared the '4' as a 'float' literal
    // so division is 'float' rather than `'integer' division
    result = (float)(val1 + val2 + val3 + val4)/4.0f;
    return result;
}

for testing, I commented out the line that tries to mess with the watchdog timer.

I ran the above code using gcc to compile/link then opened a terminal on my ubuntu linux system and here is a couple typical executions.

32
13
74
29
37.000000

and

77
53
90
49
67.250000
user3629249
  • 16,402
  • 1
  • 16
  • 17