1

Let me have two floating point variables coming as function arguments:

float fun(float x, float y) {
     // ...
}

I would like to calculate the floor of their sum. Is it possible to do it correctly not relating on current floating point rounding mode?

I mean the following. Consider the expression:

floorf(x+y)

It is possible that the exact value of the function argument (x + y) < n for some integer n will be rounded to the nearest integer n during the floating point operation, and then the floorf() function will return n instead of (n-1).

0x2207
  • 878
  • 1
  • 6
  • 20

2 Answers2

5

Here is a demonstration using the numbers given by Bathsheba and the effect of the floating point rounding mode:

#include <stdio.h>
#include <fenv.h>
#include <math.h>


int main(void) {
    double y = 0.49999999999999994;
    double x = 0.5;


    double z1 = x + y;

    // set floating point rounding downwards    
    fesetround(FE_DOWNWARD);

    double z2 = x + y;
    printf("y < 0.5: %d\nz1 == 1: %d\nz2 == 1: %d\n", y < x, z1 == 1, z2 == 1);
    printf("floor(z1): %f\nfloor(z2): %f\n", floor(z1), floor(z2));
}

y is less than 0.5, so the sum of y + 0.5 should be less than 1, but it is rounded to 1 using the default mode (z1). If the floating point rounding mode is set to round downwards, the result is less than 1 (z2), which would floor to 0. Clearly it is not possible to do this "correctly" under "any arbitrary floating point rounding mode"...

The output is

y < 0.5: 1
z1 == 1: 1
z2 == 1: 0
floor(z1): 1.000000
floor(z2): 0.000000
  • What does fesetround(FE_DOWNWARD) do internally? How long does it usually take to switch round mode (measured, say, in CPU cycles)? – 0x2207 Mar 18 '19 at 10:19
2

Yes this is possible.

A well-known example is an IEEE754 64 bit float (unusual but possible by the standard)

x = 0.5 and y = 0.49999999999999994.

(x + y) is exactly 1 and yes floorf will return 1.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • (I can't think of any examples in 32 bit IEEE754, but I can't see why there aren't any. You could test with a 2D algorithm using `nextafter`) – Bathsheba Mar 18 '19 at 10:07