2014-09-02 33 views
0

我試圖用cxx-11std::unique()找到 獨特的元素在array我小的std ::獨特的例子不工作

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <typeinfo> 


int main(){ 
    const int n=11; 
    double x[n],a3[n],a1[n]; 

    x[0]=-0.717778; 
    x[1]=-0.496843; 
    x[2]=-0.429063; 
    x[3]=-0.3596; 
    x[4]=-0.205607; 
    x[5]=0.0730536; 
    x[6]=0.138018; 
    x[7]=0.585526; 
    x[8]=2.40104; 
    x[9]=3.75268; 
    x[10]=4.55704; 

    a3[0]=0.790832; 
    a3[1]=0.569896; 
    a3[2]=0.502116; 
    a3[3]=0.432653; 
    a3[4]=0.343625; 
    a3[5]=0.512472; 
    a3[6]=0.56708; 
    a3[7]=1.01459; 
    a3[8]=2.32799; 
    a3[9]=3.67962; 
    a3[10]=4.48398; 

    std::cout.precision(10); 
    std::copy(a3,a3+n,a1); 
    for(int i=0;i<n;i++)   a1[i]+=x[i];    
    std::sort(a1,a1+n); 
    for(int i=0;i<n;i++)   std::cout << a1[i] << std::endl; 
    std::cout << "---" << std::endl; 
    int n_1=std::unique(a1,a1+n)-a1; 
    std::cout << "length of unique subvector " << n_1 << std::endl; 
    std::cout << "---" << std::endl; 
    for(int i=0;i<n_1;i++)   std::cout << a1[i] << std::endl; 
    std::cout << "---" << std::endl;  
} 

,但是當我運行此code (link to coliru) 返回:

original array 
0.073053 
0.073053 
0.073053 
0.073054 
0.138018 
0.5855256 
0.705098 
1.600116 
4.72903 
7.4323 
9.04102 
--- 
length of unique subarray 10 
--- 
unique array 
0.073053 
0.073053 
0.073054 
0.138018 
0.5855256 
0.705098 
1.600116 
4.72903 
7.4323 
9.04102 
--- 

獨特的數組仍然包含重複(所以是錯誤的)!

我做錯了什麼?

+3

另一個浮點值的比較問題.... – 2014-09-02 09:09:32

+1

浮點運算用'的std :: unique'? – 2014-09-02 09:09:35

+0

你在做什麼是期待雙重代表性是精確的...它不是(特別是在計算後) – Nim 2014-09-02 09:09:51

回答

6

讓我們嘗試用更多的精度,std::cout.precision(20)

0.073052999999999979064 
0.073053000000000034575 
0.073053999999999952308 
0.13801800000000000179 
0.58552559999999997942 
0.70509800000000000253 
1.6001160000000000938 
4.7290299999999998448 
7.4322999999999996845 
9.0410199999999996123 

由於大多數小數不能準確地用二進制浮點格式表示的,略有不同的舍入誤差引起略有不同結果。

通常,即使將相應的計算應用於數學實數,您也不能指望不同浮點計算的結果完全相等。

您可以改爲測試「幾乎相等」,仔細選擇適合您的數字域的容差。 unique允許你指定你自己的斷言,而不是一個簡單的平等的測試:

std::unique(a1,a1+n,[](double x, double y){return std::abs(x-y) < tolerance;}); 
+0

謝謝,但是我得到:'main.cpp:在lambda函數中: main.cpp:42:77:error:'tolerance' '代碼),並想知道如果你知道更多... – user189035 2014-09-02 09:22:23

+1

@ user189035:如果它是一個局部變量,那麼lambda需要捕獲它。用'[=]'或'[tolerance]'替換'[]'。 – 2014-09-02 09:23:28

1

如何:

int n_1 = std::unique(a1,a1+n, 
      [](float a, float b) 
      { 
       return std::fabs(a-b) < 10e-9; 
      } 
     ) - a1; 

Live demo link