Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is the precision loss from integer to float defined in C++?

I've a question to the code snippet below:

long l=9223372036854775807L;
float f=static_cast<float>(l);

The long value cannot be represanted exactly according to the IEEE754.

My Question is how is the lossy conversion handled:

  1. Is the nearest floating point representation taken?
  2. Is the next smaller/bigger representation taken?
  3. Or is an other approach is taken?

I'm aware of this question what happens at background when convert int to float but this does not anwser my question.

like image 741
user1235183 Avatar asked Sep 10 '19 12:09

user1235183


People also ask

How do you convert and integer into a float in C?

int total=0, number=0; float percentage=0.0; percentage=(number/total)*100; printf("%. 2f", percentage);

What is the precision of float data type in C?

float has 7 decimal digits of precision.

Why do floating-point numbers lose precision?

Floating-point decimal values generally do not have an exact binary representation. This is a side effect of how the CPU represents floating point data. For this reason, you may experience some loss of precision, and some floating-point operations may produce unexpected results.

What happens when casting from int to float?

So, when you assign an int value to float variable, the conversion of int to float automatically happens in Java. This is also called widening casting or widening primitive conversion. So, to convert an in to float using widening casting, you can just assign a value of int to float.


2 Answers

C++ defines the conversion like this (quoting latest standard draft):

[conv.fpint]

A prvalue of an integer type or of an unscoped enumeration type can be converted to a prvalue of a floating-point type. The result is exact if possible. If the value being converted is in the range of values that can be represented but the value cannot be represented exactly, it is an implementation-defined choice of either the next lower or higher representable value. [ Note: Loss of precision occurs if the integral value cannot be represented exactly as a value of the floating-point type. — end note ] If the value being converted is outside the range of values that can be represented, the behavior is undefined. If the source type is bool, the value false is converted to zero and the value true is converted to one.

The IEEE 754 standard defines conversion like this:

5.4.1 Arithmetic operations

It shall be possible to convert from all supported signed and unsigned integer formats to all supported arithmetic formats. Integral values are converted exactly from integer formats to floating-point formats whenever the value is representable in both formats. If the converted value is not exactly representable in the destination format, the result is determined according to the applicable rounding-direction attribute, and an inexact or floating-point overflow exception arises as specified in Clause 7, just as with arithmetic operations. The signs of integer zeros are preserved. Integer zeros without signs are converted to +0. The preferred exponent is 0.

Rounding modes are specified as:

4.3.1 Rounding-direction attributes to nearest

  • roundTiesToEven, the floating-point number nearest to the infinitely precise result shall be delivered; if the two nearest floating-point numbers bracketing an unrepresentable infinitely precise result are equally near, the one with an even least significant digit shall be delivered.

  • roundTiesToAway, the floating-point number nearest to the infinitely precise result shall be delivered; if the two nearest floating-point numbers bracketing an unrepresentable infinitely precise result are equally near, the one with larger magnitude shall be delivered.

4.3.2 Directed rounding attributes

  • roundTowardPositive, the result shall be the format’s floating-point number (possibly +∞) closest to and no less than the infinitely precise result

  • roundTowardNegative, the result shall be the format’s floating-point number (possibly −∞) closest to and no greater than the infinitely precise result

  • roundTowardZero, the result shall be the format’s floating-point number closest to and no greater in magnitude than the infinitely precise result.

4.3.3 Rounding attribute requirements

The roundTiesToEven rounding-direction attribute shall be the default rounding-direction attribute for results in binary formats.

So by default, your suggestion 1 would apply, but only if another mode hasn't been selected.


The C++ standard library inherits <cfenv> from the C standard. This header offers macros, functions and types for interacting with the floating point environment, including the rounding modes.

like image 186
eerorika Avatar answered Sep 20 '22 00:09

eerorika


See here:

A prvalue of integer or unscoped enumeration type can be converted to a prvalue of any floating-point type. If the value cannot be represented correctly, it is implementation defined whether the closest higher or the closest lower representable value will be selected, although if IEEE arithmetic is supported, rounding defaults to nearest. If the value cannot fit into the destination type, the behavior is undefined. If the source type is bool, the value false is converted to zero, and the value true is converted to one.

As for the rounding rules of IEEE 754, there seem to be five of them. I couldn't find any information on which ones are used in which situation, though. It looks like it's up to the implementation however, you can set the rounding mode in a C++ program as described here.

like image 42
Blaze Avatar answered Sep 19 '22 00:09

Blaze