-1

I have the following C language code which uses pointers. I have written two similar test cases. One test case matches the output of my function with macro and other with a variable equal to that macro. I understand that floating point arithmetic can produce 'false' with == operation. I have read the duplicate question - 'Is floating point math broken?' But what is the solution? How can my code pass this test without changing the test. Below is the code.

#define TEST_LBS 5.5
#define CONVERSION_FACTOR 2.20462

#include <stdio.h>

void testConvertLbsKg(void);
double convertLbsKg(double *weightLbsPtr, double *weightKilosPtr);

int main() {
    testConvertLbsKg();
    return 0;
}

void testConvertLbsKg(void) {
    double dblA, dblB, lbs = TEST_LBS;

    dblA = dblB = 0.0;
    printf("Test-1: \n");
    dblB = convertLbsKg(&lbs, &dblA);
    if (dblA == dblB && dblA == TEST_LBS / CONVERSION_FACTOR)
        printf("<PASSED> with macro\n");
    else
        printf("<!!! FAILED with macro!!!>\n");

    if (dblA == dblB && dblA == lbs / CONVERSION_FACTOR)
        printf("<PASSED> with variable\n");
    else
        printf("<!!! FAILED with variable!!!>\n");
}

double convertLbsKg(double *weightLbsPtr, double *weightKilosPtr) {
    double result;
    result = *weightLbsPtr / CONVERSION_FACTOR;

    if (weightKilosPtr != NULL) {
        *weightKilosPtr = result;
    }
    return result;
}

Output:

Test-1: 
<PASSED> with macro
<!!! FAILED with variable!!!>

It is an issue for me because it is an assignment and I can't modify the test case.

lbs == TEST_LBS //results to true

I installed C compiler like this: tutorial I am using Visual Code. Commands I used on VS Code terminal:

gcc -Wall test.c -o test
.\test.exe
chqrlie
  • 131,814
  • 10
  • 121
  • 189
R.Bansal
  • 157
  • 1
  • 6
  • Maybe one value is `5.50000000000000` and the other `5.499999999999999999` which is the same for all intents ... except for `==` with `double`s – pmg Jul 15 '22 at 17:12
  • [Cannot reproduce](https://godbolt.org/z/71664fM5Y). – n. m. could be an AI Jul 15 '22 at 17:13
  • The expression `TEST_LBS / CONVERSION_FACTOR` is between two compile-time constants and therefore as an optimization the compiler will calculate that for you. The calculation `lbs / CONVERSION_FACTOR` needs to be calculated at runtime, and might give a different result. See the duplicate for more details about the wonders of floating point arithmetic on computers, and why you can almost never use exact equality for calculated floating point values. – Some programmer dude Jul 15 '22 at 17:14
  • I have tested on 2 devices. The test passes on online compilers. But fail offline. – R.Bansal Jul 15 '22 at 17:22
  • You could try -O2 and the compiler might be smart enough to calculate `lbs / CONVERSION_FACTOR` at compile time :) – user253751 Jul 15 '22 at 17:32
  • (the reason the compile time thing is a problem is because the compiler might use slightly different math when it calculates things at compile time, than what your program uses when it calculates things at runtime) – user253751 Jul 15 '22 at 17:32
  • The solution is to change something but it is unclear what you are allowed to change. – n. m. could be an AI Jul 15 '22 at 17:37
  • I can't edit testConvertLbsKg(). I have written convertLbsKg() and I can change this method only. – R.Bansal Jul 15 '22 at 17:43
  • Also. When I do this: temp = lbs / CONVERSION_FACTOR; dblA == temp //returns true Isn't this a run-time calculation? – R.Bansal Jul 15 '22 at 17:50
  • Hard luck. As C allows computing at higher precision than specified, you get mismatch when only some expressions use that higher precision. You can play with compiler flags like `-fexcess-precision=standard`, `-mfpmath=sse` or `-ffloat-store` but there is no guarantee that will work. – numzero Jul 15 '22 at 18:14

1 Answers1

1

Your program does not have defined behavior: due to the imprecision of the double type and the fact that the C compiler may use different precision for constant expressions, the results may compare equal or not equal.

Different compilers may produce different output, the same compiler may produce different output with different compiler flags. For example, I get this output with clang -O2 on macOS:

Test-1:
<PASSED> with macro
<PASSED> with variable
chqrlie
  • 131,814
  • 10
  • 121
  • 189