[英]Is there any difference between using floating point casts vs floating point suffixes in C and C++?
這之間有區別嗎(使用浮點文字后綴):
float MY_FLOAT = 3.14159265358979323846264338328f; // f suffix
double MY_DOUBLE = 3.14159265358979323846264338328; // no suffix
long double MY_LONG_DOUBLE = 3.14159265358979323846264338328L; // L suffix
vs this(使用浮點轉換):
float MY_FLOAT = (float)3.14159265358979323846264338328;
double MY_DOUBLE = (double)3.14159265358979323846264338328;
long double MY_LONG_DOUBLE = (long double)3.14159265358979323846264338328;
在 C 和 C++ 中?
注意:對於 function 調用,go 相同:
void my_func(long double value);
my_func(3.14159265358979323846264338328L);
// vs
my_func((long double)3.14159265358979323846264338328);
// etc.
默認值為double
。 假設 IEEE754 浮點, double
是float
的嚴格超集,因此不指定f
永遠不會丟失精度。 編輯:這僅在指定可以由float
表示的值時才成立。 如果發生舍入,由於舍入兩次,這可能不是嚴格正確的,請參閱 Eric Postpischil 的回答。 因此,您還應該使用f
后綴作為浮點數。
這個例子也有問題:
long double MY_LONG_DOUBLE = (long double)3.14159265358979323846264338328;
這首先給出一個double
常量,然后將其轉換為long double
。 但是因為你從一個double
開始,你已經失去了永遠不會回來的精度。 因此,如果要在long double
常量中使用全精度,則必須使用L
后綴:
long double MY_LONG_DOUBLE = 3.14159265358979323846264338328L; // L suffix
使用后綴和強制轉換是有區別的; 8388608.5000000009f
和(float) 8388608.5000000009
在常見的 C 實現中具有不同的值。 這段代碼:
#include <stdio.h>
int main(void)
{
float x = 8388608.5000000009f;
float y = (float) 8388608.5000000009;
printf("%.9g - %.9g = %.9g.\n", x, y, x-y);
}
打印“8388609 - 8388608 = 1”。 在 Apple Clang 11.0 和其他使用 IEEE-754 binary32 for float
和 binary64 for double
的正確舍入的實現中。 (C 標准允許實現使用 IEEE-754 正確舍入以外的方法,因此其他 C 實現可能有不同的結果。)
原因是(float) 8388608.5000000009
包含兩個舍入操作。 使用后綴8388608.5000000009f
直接轉換為float
,因此為了適合float
必須丟棄的部分 0.5000000009 會被直接檢查以查看它是否大於.5。 是的,所以結果向上舍入到下一個可表示的值 8388609。
沒有后綴, 8388608.5000000009
首先被轉換為double
。 當考慮必須丟棄的部分 0.0000000009 時,發現它小於截斷點的低位 ½。 (那里低位的值是.00000000186264514923095703125,一半是.000000000931322574615478515625。)所以結果向下舍入,我們得到8388608.5作為double
精度數。 當強制轉換將此四舍五入為float
時,必須丟棄的部分是.5,正好在可表示的數字 8388608 和 8388609 之間。打破平局的規則將其四舍五入為具有偶數低位 8388608 的值。
(另一個例子是“7.038531e-26”; (float) 7.038531e-26
不等於7.038531e-26f
。當float
是 binary32 並且double
是 binary64 時,這是唯一一個有效數字少於八位的數字,除了課程“-7.038531e-26”。)
雖然在浮點常量中省略 f 不會丟失精度,但這樣做可能會讓人感到意外。 考慮一下:
#include <stdio.h>
#define DCN 0.1
#define FCN 0.1f
int main( void)
{
float f = DCN;
printf( "DCN\t%s\n", f > DCN ? "more" : "not-more");
float g = FCN;
printf( "FCN\t%s\n", g > FCN ? "more" : "not-more");
return 0;
}
這(使用 gcc 9.1.1 編譯)產生 output
DCN more
FCN not-more
解釋是在 f > DCN 中,編譯器將 DCN 設為 double 類型,因此將 f 提升為 double,並且
(double)(float)0.1 > 0.1
就我個人而言,在我需要浮點常量的(罕見)場合,我總是使用“f”后綴。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.