Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
532 views
in Technique[技术] by (71.8m points)

c - When does appending an 'f' change the value of a floating constant when assigned to a `float`?

Applying an f to a floating point constant does not seem to make a difference when assigning the constant to a float.

int main(void) {
  float f;
  //  1 2345678901234567
  f = 3.1415926535897932;
  printf("%.6a  %.8f  pi 3.1415926535897932
", f, f);
  f = 3.1415926535897932f;              // v
  printf("%.6a  %.8f  pi 3.1415926535897932f
", f, f);
}

With or without the f, the value is the same

// value       value          code 
0x1.921fb6p+1  3.14159274  pi 3.1415926535897932
0x1.921fb6p+1  3.14159274  pi 3.1415926535897932f

Why ever use f?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a self answer per Answer Your Own Question.

Appending an f makes the constant a float and sometimes makes a value difference.


Type difference: double to float.

A well enabled compiler may emit a warning when the f is omitted too.

  float f = 3.1415926535897932;  // May generate a warning

warning: conversion from 'double' to 'float' changes value from '3.1415926535897931e+0' to '3.14159274e+0f' [-Wfloat-conversion]


To make a value difference, watch out for potential double rounding issues.

The first rounding is due to code's text being converted to the floating point type.

the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner. C17dr § 6.4.4.2 3

A very common implementation-defined manner is to convert the source code text to the closest double (without the f) or to the closest float with the f suffix. Lesser quality implementations sometimes form the 2nd best choice.

Assignment of a double FP constant to a float incurs another rounding.

If the value being converted is in the range of values that can be represented but cannot be represented exactly, the result is either the nearest higher or nearest lower representable value, chosen in an implementation-defined manner. C17dr § 6.3.1.4 2

A very common implementation-defined manner is to convert the double to the closest float - ties to even. (Compile time rounding may be affected by various compiler settings.)

Double rounding value change

Consider the case when source code uses a value very close to half-way between 2 float values.

Without an f, the rounding of code to a double may result in a value exactly half-way between 2 floats. The conversion of the double to float then could differ from "with an f".

With an f, the conversion results in the closest float.

#include <math.h>
#include <stdio.h>
int main(void) {
  float f;
  f = 10000000.0f;
  printf("%.6a  %.3f  10 million
", f, f);
  f = nextafterf(f, f + f);
  printf("%.6a  %.3f  10 million - next float
", f, f);
  puts("");
  f = 10000000.5000000001;
  printf("%.6a  %.3f  10000000.5000000001
", f, f);
  f = 10000000.5000000001f;
  printf("%.6a  %.3f  10000000.5000000001f
", f, f);
  puts("");
  f = 10000001.4999999999;
  printf("%.6a  %.3f  10000001.4999999999
", f, f);
  f = 10000001.4999999999f;
  printf("%.6a  %.3f  10000001.4999999999f
", f, f);
}

Output

0x1.312d00p+23  10000000.000  10 million
0x1.312d02p+23  10000001.000  10 million - next float

// value        value         source code
0x1.312d00p+23  10000000.000  10000000.5000000001
0x1.312d02p+23  10000001.000  10000000.5000000001f // Different, and better

0x1.312d04p+23  10000002.000  10000001.4999999999
0x1.312d02p+23  10000001.000  10000001.4999999999f // Different, and better

Rounding mode

The issue about double1 rounding is less likely when the rounding mode is up, down or towards zero. It arises when the 2nd rounding compounds the direction on half-way cases.

Occurrence rate

Issue occurs when code converts inexactly to a double that is very near half-way between 2 float values - so relatively rare. Issue applies even if the code constant was in decimal or hexadecimal form. With random constants: about 1 in 230.

Recommendation

Rarely a major concern, yet an f suffix is better to get the best value for a float and quiet a warning.


1 double here refers to doing something twice, not the the type double.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...