簡體   English   中英

在 C 和 C++ 中使用浮點轉換與浮點后綴有什么區別?

[英]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.

有關的:

  1. 長雙字面值的 C++ 后綴是什么?
  2. https://en.cppreference.com/w/cpp/language/floating_literal

默認值為double 假設 IEEE754 浮點, doublefloat的嚴格超集,因此不指定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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM