簡體   English   中英

C / C ++中浮點常數的緊湊無損表示

[英]Compact lossless representation of floating point constants in C/C++

我有一個用C ++編寫的程序,它為數學計算生成C源代碼。 我注意到常量在生成的代碼中占用了很多空間,我正在尋找更緊湊的表示。

要生成常量,我現在使用:

double v = ...
cfile << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << v;

我很確定這是一種無損代表,但它也非常臃腫。 例如,零和一個將表示為0.0000000000000000e + 00和1.0000000000000000e + 00。 並且“0” 或“1.” 攜帶同樣多的信息。

有沒有辦法以更緊湊但仍然無損的方式打印常量? 對於人類讀者來說,它不需要看起來很好,只需在純C代碼中進行編譯(如果是C99,我更願意,如果它也是有效的C ++)。 十六進制可以是可移植的。

編輯:刪除了代碼片段中的std::fixed

您可以使用十六進制浮點( C中的printf()的格式說明符%a ; 它被定義為保留所有精度位(C11,7.21.6.1p8, a,A說明符)。

cfile << std::hexfloat << v;

如果你的編譯器/標准庫不支持hexfloat ,你可以使用C99 %a printf說明符(這是等效的,如C ++ 11表88中第22.4.2.2.2節所述):

printf("%a", v);

例如,以下程序是有效的C99:

#include <stdio.h>
int main() {
   double v = 0x1.8p+1;
   printf("%a\n", v);
}

您生成的源文件將無效C ++ 11,因為相當荒謬的是C ++ 11不支持十六進制浮點文字。 但是,許多C ++ 11編譯器支持C99十六進制浮點文字作為擴展。

這不是表示,語言或標准庫的問題,而是算法的問題。 如果你有一個代碼生成器,那么...為什么不將生成的代碼更改為最佳(=最短,具有所需精度)表示? 這是你手工編寫代碼時所做的。

在假設的put_constant(double value)例程中,您可以檢查您必須編寫的值

  • 它是整數嗎? 不要使用std::fixedset_precision膨脹代碼,只需轉換為整數並添加一個點。
  • 嘗試將其轉換為具有默認設置的字符串,然后將其轉換回double ,如果沒有更改,則默認(短)表示就足夠了。
  • 將其轉換為實際實現的字符串,並檢查其長度。 如果它超過N(見下文),請使用另一種表示,否則只需編寫它。

當浮點數具有大量數字時,可能的(短)表示是使用它們的存儲器表示 有了這個你有一個非常固定的開銷,長度不會改變所以你應該只應用它很長的數字。 一個簡單的例子來說明它是如何工作的:

#define USE_L2D __int64 ___tmp = 0;
#define L2D(x) (double&)(___tmp=x)

int main(int argc, char* argv[])
{
    // 2.2 = in memory it is 0x400199999999999A

    USE_L2D
    double f1 = L2D(0x400199999999999A);
    double f2 = 123456.1234567891234567;

    return 0;
}

首先,當你第一次說std::scientific ,然后std::fixed時,你就是自相矛盾的。 第二,你可能也不想要。 默認格式通常旨在實現此目的。 默認格式沒有名稱,也沒有操縱器,但如果沒有指定其他格式,則可以獲得,並且可以設置(如果其他代碼設置了不同的格式),使用:

cfile.setf( std::ios_base::fmtflags(), std::ios_base::floatfield );

我建議用這個。 (當然,你仍然需要精確度。)

我不確定你像這樣毫無損失地通過浮動點。 浮點必然是有損的。 雖然它們可以精確地表示值的子集,但您不能包含所有有效數字 - 不同的硬件可能具有不同的表示,因此您無法保證不會丟失信息。 即使您可以將其全部傳遞,因為接收硬件可能無法表示該值。

但是,普通的ofstream :: operator <<會打印出所需的數字,因此實際上並不需要使問題復雜化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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