Welcome to Logically Proven blog.

This post demonstrates

Floating-point calculations are carried out internally with extra precision, and then rounded to fit into the destination type.

IEEE 754 defines the following

1. Round to nearest (

2. Round toward plus infinity (

3. Round toward minus infinity (

4. Round toward zero (

You can decide the following destination types when rounding the float values -

These functions are available in the header

So don't forget to include this header file while working with rounding the float values.

If x is

If x is

All these rounding modes are defined in the header file #include <fenv.h> as shown below -

The macro values may

The decimal representation of hex values are useful while setting the rounding mode. This is explained in the later section.

Now we look into each rounding mode.

This is the

All results are rounded to the smallest representable value which is greater than the result. In other words the values are rounded towards

All results are rounded to the largest representable value which is less than the result. In other words the values are rounded towards

All results are rounded to the largest representable value which is less than the result. In other words, if the result is

E.g. FE_TOWARDZERO(-0.22) returns -0.

This is because the negative zero can also result from some operations on infinity, such as 4/-infinity.

C++ Example: Rounding is guaranteed only if

Include header files

Please write your comments if you find anything is incorrect or do you want to share more information about the topic discussed above.

Logically Proven

Learn, Teach, Share

This post demonstrates

*different modes of rounding float values in C/C++ programming.*Floating-point calculations are carried out internally with extra precision, and then rounded to fit into the destination type.

**ROUNDING MODES:**IEEE 754 defines the following

**four**possible rounding modes:1. Round to nearest (

*FE_TONEAREST*)2. Round toward plus infinity (

*FE_UPWARD*)3. Round toward minus infinity (

*FE_DOWNWARD*)4. Round toward zero (

*FE_TOWARDZERO*)**RETURN VALUES:**You can decide the following destination types when rounding the float values -

These functions are available in the header

**#include <math.h>**So don't forget to include this header file while working with rounding the float values.

**rint() -**this function returns the**integral**value depending on rounding mode.**Syntax:**//x is the float value double rint(double x)

If x is

**+/-**infinity, rint() returns x.If x is

**NaN**, NaN is returned.**rintf() -**this function returns the**single-precision**value depending on rounding mode.**Syntax:**//x is the float value float rint(floatx)

**#include <fenv.h>**All these rounding modes are defined in the header file #include <fenv.h> as shown below -

/* FPU control word rounding flags */ #define FE_TONEAREST 0x0000 //decimal value: 0 #define FE_DOWNWARD 0x0400 //decimal value: 1024 #define FE_UPWARD 0x0800 //decimal value: 2048 #define FE_TOWARDZERO 0x0c00 //decimal value: 3072

The macro values may

**change**depending on compiler.The decimal representation of hex values are useful while setting the rounding mode. This is explained in the later section.

Now we look into each rounding mode.

**Round to nearest (FE_TONEAREST):**This is the

**default**mode. In this mode results are rounded to the**nearest**representable value. If the result is midway between two representable values, the even representable is chosen. Even here means the lowest-order bit is zero. This rounding mode prevents statistical bias and guarantees numeric stability.**Round toward plus infinity (FE_UPWARD):**All results are rounded to the smallest representable value which is greater than the result. In other words the values are rounded towards

**+infinity**.**Round toward minus infinity (FE_DOWNWARD):**All results are rounded to the largest representable value which is less than the result. In other words the values are rounded towards

**-infinity**.**Round toward zero (FE_TOWARDZERO):**All results are rounded to the largest representable value which is less than the result. In other words, if the result is

**negative**it is rounded**up**; if it is**positive**, it is rounded**down**.**Important note**- If the result is too small to be represented, it is rounded to zero. However, the*sign of the result*is preserved.E.g. FE_TOWARDZERO(-0.22) returns -0.

This is because the negative zero can also result from some operations on infinity, such as 4/-infinity.

**Get and Set Rounding Mode:****int fegetround(void)**- This function is used to to return the currently**selected**rounding mode.**int fesetround(int round) -****This function is used to**

**set**the one of the rounding modes. The argument 'round' to this function is either an decimal representation or macro name (e.g. FE_UPWARD) of rounding mode. This function returns**non-zero**value if it**fails**to set rounding mode else**zero**if**success**.**Note**- Avoid changing the rounding mode if possible. It can be**expensive**operation which leads to run the code slower than expected. For more details see your compiler documentation.**C Example:**#include <stdio.h> #include <stdlib.h> #include <fenv.h> #include <math.h> int main() { float fValue; fValue = 10.22; //by default FE_TONEAREST printf("\nFE_TONEAREST:%f\n",rintf(fValue)); //set to FE_UPWARD, returns zero if success //set using macro name printf("Set to FE_UPWARD: %d\n",fesetround(FE_UPWARD)); printf("Currently the rounding mode is :%d\n",fegetround()); printf("FE_TOUPWARD(10.22):%f\n",rintf(fValue)); //set to FE_DOWNWARD, returns zero if success //FE_DOWNWARD integral representation is 1024 //set using integral representation of macro name printf("Set to FE_DOWNWARD: %d\n",fesetround(1024)); printf("Currently the rounding mode is :%d\n",fegetround()); printf("FE_DOWNUPWARD(10.22):%f\n",rintf(fValue)); //set to FE_TOWARDZERO, returns zero if success printf("Set to FE_TOWARD: %d\n",fesetround(FE_TOWARDZERO)); printf("Currently the rounding mode is :%d\n",fegetround()); printf("FE_TOWARDZERO(-0.22):%f\n",rintf(-0.22)); printf("Currently the rounding mode is :%d\n",fegetround()); printf("FE_TOWARDZERO(1.22):%f\n",rintf(1.52)); return 0; } /* output: FE_TONEAREST:10.000000 Set to FE_UPWARD: 0 Currently the rounding mode is :2048 FE_TOUPWARD(10.22):11.000000 Set to FE_DOWNWARD: 0 Currently the rounding mode is :1024 FE_DOWNUPWARD(10.22):10.000000 Set to FE_TOWARD: 0 Currently the rounding mode is :3072 FE_TOWARDZERO(-0.22):-0.000000 Currently the rounding mode is :3072 FE_TOWARDZERO(1.22):1.000000 */

C++ Example: Rounding is guaranteed only if

**#pragma STDC FENV_ACCESS ON**

is set.Include header files

**fenv.h**and**math.h**if you are using older versions of C++. C++11 version and later supports**cfenv.h**and**cmath.h**header files.#include <iostream> #include <string> #include <cfenv> #include <cmath> int main() { #pragma STDC FENV_ACCESS ON std::fesetround(FE_DOWNWARD); std::cout << "rounding down: \n" << " rintf(2.8) = " << std::rint(2.8) << "\n\n"; } /*output: rounding down: rint(2.8) = 2 */

Please write your comments if you find anything is incorrect or do you want to share more information about the topic discussed above.

Logically Proven

Learn, Teach, Share

So the two functions that you have used are defined by compiler..please disclose your complete header definition file...if I use the pragma in the header, will it work..?

ReplyDeleteHi Mayukh,

Delete1. All the header files specified in the code snippets are inbuilt from C++ libraries. If you want to see the complete header file definition, right-click on the included header file in your code, select open

2. Yes, you can use #pragma in the header file. The header file definitions are added into the main file (main) at the time of compilation. So my answer is - it works.

Please let me know if you have any questions. Thanks for your visit to the page.