我小的std ::独特的例子不工作

问题描述:

我试图用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

让我们尝试用更多的精度,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

如何:

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

Live demo link