当分配给“float"时,附加“f"何时会更改浮动常量的值? [英] When does appending an 'f' change the value of a floating constant when assigned to a `float`?

查看:23
本文介绍了当分配给“float"时,附加“f"何时会更改浮动常量的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

f 应用于浮点常量似乎在将常量分配给 float 时没有什么区别.

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

有无f,值都一样

//值值代码0x1.921fb6p+1 3.14159274 pi 3.14159265358979320x1.921fb6p+1 3.14159274 pi 3.1415926535897932f

为什么要使用 f?

解决方案

这是一个自我回答 回答你自己的问题.

附加一个 f 使常量成为一个 float 并且 sometimes 产生一个值差异.


类型

类型区别:doublefloat.

f 也被省略时,启用良好的编译器可能会发出警告.

 float f = 3.1415926535897932;//可能会产生警告

<块引用>

警告:从 'double' 到 'float' 的转换会将值从 '3.1415926535897931e+0' 更改为 '3.14159274e+0f' [-Wfloat-conversion]


价值

要产生价值差异,请注意潜在的双舍入 问题.

第一次舍入是由于代码的文本被转换为浮点类型.

<块引用>

结果要么是最接近的可表示值,要么是紧邻最接近的可表示值的较大或较小的可表示值,以实现定义的方式选择.C17dr § 6.4.4.2 3

鉴于这两种选择,一个非常常见实现定义的方式是将源代码文本转换为最接近的double(没有f) 或以 f 为后缀的最接近的 float.质量较差的实现有时会形成第二接近的选择.

double FP 常量分配给 float 会导致另一个舍入.

<块引用>

如果要转换的值在可以表示但不能准确表示的值范围内,则结果是最接近的较高或最近的较低可表示值,以实现定义的方式选择.C17dr § 6.3.1.4 2

一个非常常见的实现定义的方式是将double转换为最接近的float - 与偶数关系.(注意:编译时舍入可能会受到各种编译器设置的影响.)

双舍入值变化

考虑源代码使用的值非常接近在两个 float 值之间的中间值.

如果没有 f,将代码四舍五入到 double 可能会导致值恰好介于 2 个 float 之间.doublefloat 的转换可能不同于使用 f".

使用 f,转换结果是最接近的 float.

例子:

#include <math.h>#include <stdio.h>诠释主要(无效){浮动 f;f = 10000000.0f;printf("%.6a %.3f 1000万
", f, f);f = nextafterf(f, f + f);printf("%.6a %.3f 1000 万 - 下一个浮点数
", f, f);放(");f = 10000000.5000000001;printf("%.6a %.3f 10000000.5000000001
", f, f);f = 10000000.5000000001f;printf("%.6a %.3f 10000000.5000000001f
", f, f);放(");f = 10000001.4999999999;printf("%.6a %.3f 10000001.4999999999
", f, f);f = 10000001.4999999999f;printf("%.6a %.3f 10000001.4999999999f
", f, f);}

输出

0x1.312d00p+23 10000000.000 1000万0x1.312d02p+23 10000001.000 1000 万 - 下一个浮点数//值值源代码0x1.312d00p+23 10000000.000 10000000.50000000010x1.312d02p+23 10000001.000 10000000.5000000001f//不同,更好0x1.312d04p+23 10000002.000 10000001.49999999990x1.312d02p+23 10000001.000 10000001.4999999999f//不同,更好

舍入模式

当舍入模式为向上、向下或接近零时,双1 舍入的问题不太可能发生.当第二次舍入在中途情况下复合方向时会出现问题.

发生率

当代码不精确地转换为非常接近 2 个 float 值的中间值的 double 时,就会出现问题 - 因此比较少见.即使代码常量是十进制或十六进制形式,问题也适用.使用随机常数:大约 2 分之一30.

推荐

很少是主要问题,但 f 后缀更好地获得 float 的最佳值并消除警告.


1 double 这里指的是做某事两次,而不是 double 类型.

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?

解决方案

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

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]


Value

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

Given those two choices, 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 closest 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 - with ties to even. (Note: 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.

Example:

#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. Issue 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.

这篇关于当分配给“float"时,附加“f"何时会更改浮动常量的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆