1

I am writing code to find if a person breaks world record in running race. The first input is number of test cases( t ), then the next inputs are conditions faced while running ( k1, k2, k3, v) If final speed is equal to or greater than 9.58 the output should be no. While if final speed is less than 9.58 the output should be yes. But in following test case I am getting wrong output for second case:

3
1.0 1.0 1.0 10.45
1.0 1.0 1.0 10.44
1.0 1.0 0.9 10.44  

I get Output :

YES
YES
NO

I want output :

YES
NO
NO
   

int main(void)
{
    int t;
    scanf("%d", &t);
    float k1, k2, k3, v, speed_with_fact[t], final_speed[t];
    for (int i = 0; i < t; i++)
    {
        scanf("%f %f %f %f", &k1, &k2, &k3, &v);
        speed_with_fact[i] = 100 / (k1 * k2 * k3 * v);
        speed_with_fact[i] = (int)(speed_with_fact[i] * 100 + 0.5);
        // printf("%f\n " ,speed_with_fact[i]);
        final_speed[i] = speed_with_fact[i] / 100;
        // printf("%f\n " ,final_speed[i]);
    }
    for (int j = 0; j < t; j++)
    {
        //printf("%f\n " ,final_speed[j]);
        if (final_speed[j] < 9.58)
        {

            printf("YES\n");
        }
        else 
        {
            printf("NO\n");
        }
    }

    return 0;
}
Alcon Blue
  • 13
  • 4
  • 1
    Thank you @anastaciu for the edit, I am new to stackoverflow and am not much aware about its interface. – Alcon Blue Apr 03 '21 at 14:35
  • 2
    What is the point of `if (final_speed[j] == 9.580000)`? Surely that is covered by `if (final_speed[j] >= 9.580000)` -- and why have either of those rather than a simple `else`? Either `final_speed[j] < 9.580000` or it isn't – John Coleman Apr 03 '21 at 14:35
  • 1
    `float` sucks. **NEVER** use `float`: https://ideone.com/ZWVR3B ... (possibly unless you do embedded or other constrained environments). Remember to use `"%lf"` with scanf when entering `double`s – pmg Apr 03 '21 at 14:40
  • Why do you expect the answer for the second case to be "NO"? It might help you debug if you also printed `final_speed[j]` for each trial. – John Bollinger Apr 03 '21 at 14:42
  • @JohnBollinger, if you run the program with the uncommented print, it will print `9.580000` for the second case so the OP confusion is understandable. – anastaciu Apr 03 '21 at 14:45
  • 1
    hm. I'm not so sure whether using `double` instead of `float` is the correct answer here. I think it might be better to compare the hundterths of a second as integers, so skip the last division by 100 and compare against 958. – M Oehm Apr 03 '21 at 14:46
  • @MOehm that will work too, nevertheless, it's always better to use `double` so it's good advice. – anastaciu Apr 03 '21 at 14:52
  • 1
    @anastaciu: Hm. The problem is that the code above mixes float and double. If you compare against an explicit float, `9.58f`, the code above works, too. Because the WR is saved to on hundreth of a second, I was reminded of the "money as floating-point" pitfall when calculating the change. – M Oehm Apr 03 '21 at 15:17
  • @MOehm, yes, you are correct, didn't though about that. – anastaciu Apr 03 '21 at 15:21

1 Answers1

1

The value of final_speed[j] being 9.58 is an aproximation, if you test print it with printf("%.10f\n " ,final_speed[j]); you'll see that the value is not exactly 9.58 (I got 9.5799999237). Floating-point arithmetic is very inexact and is the source of many problems like your own.

In your particular case, since the type of the literal 9.58 will be double by default it means that you are comparing float with double, this is fixed if you use double variables.

You could force a float literal using 9.58f as very accurately pointed out by MOhem and it would also work, but using double is advised.

int main(void)
{
    int t;
    scanf("%d", &t);
    double k1, k2, k3, v, speed_with_fact[t], final_speed[t]; //<-- here
    for (int i = 0; i < t; i++)
    {
        scanf("%lf %lf %lf %lf", &k1, &k2, &k3, &v); //<-- here
        speed_with_fact[i] = 100 / (k1 * k2 * k3 * v);
        //...
}

Another good suggestion by MOehm's will also work and is a good option, maybe even better as it simplifies the comparison to int vs int.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • 1
    Using `float` is like using a plastic ruler that was left in the Sun for too long :-) – pmg Apr 03 '21 at 15:18
  • 1
    @pmg, lol, that's... a nice analogy, I'll have to write that down so I don't forget. – anastaciu Apr 03 '21 at 15:22
  • 1
    @AlconBlue: A float has lesser precision than a double, but it is still good enough for your problem. The issue with your code is that you (inadvertently) compare your float value with the double value `9.58`. In C, a floating-point constant is considered a double. If you want to specify a float value, you must explicitly use an `f` suffix: `9.58f`. Neither float nor double can represent 9.58 exactly, but double gets closer: 9.58000000000000007105 vs. 9.5799999237. With such comparisons, it's always which way the incorrectness falls: Is the real value a bit smarre or a bit larger? – M Oehm Apr 03 '21 at 15:34
  • @MOehm I did include your remarks in my answer, sourced, of course, I hope you don't mind. – anastaciu Apr 03 '21 at 15:38
  • 1
    Not at all! Thank you. – M Oehm Apr 03 '21 at 15:43