理智检查 - 浮点比较 [英] sanity check - floating point comparison

查看:79
本文介绍了理智检查 - 浮点比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



模板< class T>内联bool isEqual(const T& a,const T& b,

const T epsilon = std :: numeric_limits< T> :: epsilon())

{

const T diff = a - b;

return(diff< = epsilon)&& (差异> = -epsilon);

}


int main()

{

std :: deque< double> pt;

pt.push_back(2.3123);

pt.push_back(4.3445);

pt.push_back(1.343);

pt.push_back(4.3445);

pt.push_back(4.3445);

pt.push_back(2.3123);

的std ::双端队列<双> jt;

jt.push_back(4.3445);

jt.push_back(2.3123);


std :: deque< double> ;结果;

//结果应该有 - 1,3,4,0,5

for(int idx(0); idx< jt。 size(); ++ idx)

{

for(int kdx(0); kdx< pt.size(); ++ kdx)

{

if(isEqual< double>(jt [idx],pt [kdx]))

{

结果。 push_back(kdx);

}

}

}

std :: copy(results.begin() ,results.end(),

std :: ostream_iterator< int>(std :: cout," \ n"));

}


我的意图。我将在pt容器中搜索jt

容器中的值。如果找到,我会在结果容器中存储

索引/位置,其中值是在pt容器中找到的。对于

示例:在pt容器中搜索第一个元素的pt容器。所以我

在1号,3号和4号位置找到4个。类似于2. 2,在0和5的pt容器中找到了




结果将打印,1,3,4,0,5。工作。


让我感到紧张的是浮点比较。

后,所有numeric_limits都没有在一个平台上定义(使用gcc 2.96)。

那就是说,我选择使用迭代器 - 我认为std :: distance

但是我最终还是会做浮点比较,在这种情况下,我自己的版本(使用我自己的比较器 - isEqual)最好的是
。正确吗?


template <class T> inline bool isEqual( const T& a, const T& b,
const T epsilon = std::numeric_limits<T>::epsilon() )
{
const T diff = a - b;
return ( diff <= epsilon ) && ( diff >= -epsilon );
}

int main()
{
std::deque<double> pt ;
pt.push_back ( 2.3123 );
pt.push_back ( 4.3445 );
pt.push_back ( 1.343 );
pt.push_back ( 4.3445 );
pt.push_back ( 4.3445 );
pt.push_back ( 2.3123 );
std::deque<double> jt ;
jt.push_back ( 4.3445 );
jt.push_back ( 2.3123 );

std::deque<double> results;
// results should have - 1, 3, 4, 0, 5

for ( int idx ( 0 ) ; idx < jt.size(); ++idx )
{
for ( int kdx ( 0 ); kdx < pt.size(); ++kdx )
{
if ( isEqual<double>( jt [ idx ], pt [ kdx ] ) )
{
results.push_back ( kdx );
}
}
}
std::copy ( results.begin(), results.end(),
std::ostream_iterator<int> ( std::cout, "\n" ) );
}

My intent. I''ll search the pt container for the values in the jt
container. If found, I''ll store - in the result container - the
index/location where the value was found in the pt container. For
example: Search pt container for first element in jt container. So I
found 4 at postions 1, 3 and 4. Similarily for 2. 2 was found within
the pt container at 0 and 5.

Result will print, 1, 3, 4, 0, 5. Works.

What makes me nervous though is the floating point comparsion. After
all numeric_limits is not defined on one platform (using gcc 2.96).
That said, I was opting to use iterators with - I think std::distance
but I''ll end up doing floating point comparison anyways, in which case
my own version ( with my own comparator - isEqual) works best. Correct?

推荐答案

在消息< 11 ****************** ****@u72g2000cwu.googlegroups .com> ;,

ma740988< ma ****** @ gmail.com>写
In message <11**********************@u72g2000cwu.googlegroups .com>,
ma740988 <ma******@gmail.com> writes

模板< class T>内联bool isEqual(const T& a,const T& b,
const T epsilon = std :: numeric_limits< T> :: epsilon())
{
const T diff = a - b;
返回(差异< = epsilon)&& (diff> = -epsilon);
}
int main()
{
std :: deque< double> pt;
pt.push_back(2.3123);
pt.push_back(4.3445);
pt.push_back(1.343);
pt.push_back(4.3445);
pt.push_back(4.3445);
pt.push_back(2.3123);

std :: deque< double> jt;
jt.push_back(4.3445);
jt.push_back(2.3123);

std :: deque< double>结果;
//结果应该有 - 1,3,4,0,5

(int idx(0); idx< jt.size(); ++ idx)
{
for(int kdx(0); kdx< pt.size(); ++ kdx)
{
if(isEqual< double>(jt [idx] ,pt [kdx]))
{
results.push_back(kdx);
}
}
}
std :: copy(results.begin) (),results.end(),
std :: ostream_iterator< int>(std :: cout," \ n"));
}

我的意图。我将在pt容器中搜索jt
容器中的值。如果找到,我将 - 在结果容器中 - 存储在pt容器中找到值的
索引/位置。对于
示例:在jt容器中搜索第一个元素的pt容器。所以我在位置1,3和4处找到了4个。在0和5的pt容器中找到了2. 2。

结果将打印,1, 3,4,0,5。作品。

让我紧张的是浮点比较。
之后所有numeric_limits都没有在一个平台上定义(使用gcc 2.96)。




那说,我选择使用迭代器 - 我认为std :: distance


?使用迭代器与索引是一个完全不同的问题

如何比较存储的值。

但我最终会做浮点比较,在这种情况下
我自己的版本(使用我自己的比较器 - isEqual)效果最好。正确吗?

template <class T> inline bool isEqual( const T& a, const T& b,
const T epsilon = std::numeric_limits<T>::epsilon() )
{
const T diff = a - b;
return ( diff <= epsilon ) && ( diff >= -epsilon );
}

int main()
{
std::deque<double> pt ;
pt.push_back ( 2.3123 );
pt.push_back ( 4.3445 );
pt.push_back ( 1.343 );
pt.push_back ( 4.3445 );
pt.push_back ( 4.3445 );
pt.push_back ( 2.3123 );
std::deque<double> jt ;
jt.push_back ( 4.3445 );
jt.push_back ( 2.3123 );

std::deque<double> results;
// results should have - 1, 3, 4, 0, 5

for ( int idx ( 0 ) ; idx < jt.size(); ++idx )
{
for ( int kdx ( 0 ); kdx < pt.size(); ++kdx )
{
if ( isEqual<double>( jt [ idx ], pt [ kdx ] ) )
{
results.push_back ( kdx );
}
}
}
std::copy ( results.begin(), results.end(),
std::ostream_iterator<int> ( std::cout, "\n" ) );
}

My intent. I''ll search the pt container for the values in the jt
container. If found, I''ll store - in the result container - the
index/location where the value was found in the pt container. For
example: Search pt container for first element in jt container. So I
found 4 at postions 1, 3 and 4. Similarily for 2. 2 was found within
the pt container at 0 and 5.

Result will print, 1, 3, 4, 0, 5. Works.

What makes me nervous though is the floating point comparsion. After
all numeric_limits is not defined on one platform (using gcc 2.96).
?
That said, I was opting to use iterators with - I think std::distance
? Use of iterators versus indexing is a completely different question
from how to compare the stored values.
but I''ll end up doing floating point comparison anyways, in which case
my own version ( with my own comparator - isEqual) works best. Correct?



IMO no。


我无法想象有人故意开始在
$ b上生成编译器$ b,相同的浮动文字2.3123等,在代码中的每个地方内部都不会产生相同的

倍值,如果

您使用相同的编译器标志。 (如果你通过算术生成数字,那么它当然是另一回事。)


即使编译器确实产生了不同的值对于相同的文字,

没有理由认为结果会通过isEqual()。

epsilon()在数值分析中有用,但我不要认为这是一个合适的b $ b。实际上它保证如果X == 1.0,(a)X和

X + epsilon()是不同的值,(b)X和X + epsilon()/ 2不是,

但是对于X的其他值,其中一个断言可能不正确。


要正确指定模糊浮点比较,通常需要

对建模域名的一些了解,但在这里你试图再次猜测一个可能甚至不存在的编译器问题。


最后,如果你真的必须使用你自己的比较器,不要叫它

isEqual。


-

Richard Herring


IMO no.

I can''t imagine anyone deliberately setting out to produce a compiler on
which the same floating literal 2.3123 etc., wouldn''t produce the same
double value internally in each place in the code where it''s used, if
you use the same compiler flags. (If you''re generating the numbers by
arithmetic it''s a different matter, of course.)

Even if the compiler did produce different values for the same literal,
there''s no reason to suppose that the results would pass isEqual().
epsilon() has its uses in numerical analysis, but I don''t think this is
an appropriate one. In effect it''s guaranteed that if X==1.0, (a) X and
X + epsilon() are distinct values and (b) X and X + epsilon()/2 are not,
but for other values of X one of those assertions may not be true.

To specify fuzzy floating-point comparisons correctly you generally need
some knowledge of the domain being modelled, but here you''re trying to
second-guess a compiler problem that probably doesn''t even exist.

Finally, if you really must use your own comparator, don''t call it
isEqual.

--
Richard Herring




IMO没有。

我无法想象有人故意开始在
上生成一个编译器,其中相同的浮动文字2.3123等,不会产生相同的
代码中每个位置的内部双值在哪里使用它,如果你使用相同的编译器标志。 (如果你通过算术生成数字,那当然是另一回事。)


IMO no.

I can''t imagine anyone deliberately setting out to produce a compiler on
which the same floating literal 2.3123 etc., wouldn''t produce the same
double value internally in each place in the code where it''s used, if
you use the same compiler flags. (If you''re generating the numbers by
arithmetic it''s a different matter, of course.)



如果我理解正确的话。简单地做

if(jt [idx] == pt [kdx]))

就足够了?


So if I understand you correctly. Simply doing
if ( jt [ idx ] == pt [ kdx ] ) )
would suffice?

你好,


ma740988写道:
Hello,

ma740988 wrote:

模板< class T>内联bool isEqual(const T& a,const T& b,
const T epsilon = std :: numeric_limits< T> :: epsilon())
{
const T diff = a - b;
返回(差异< = epsilon)&& (差异> = -epsilon);
}



这个epsilon是1的差异,而最小的值是严格的更大

比1.如果你取1000000且最小值严格大于

1000000,那么你将看到,差异大于

epsilon。我不认为你想要那些值得等于返回

false。

int main()
{
std双端队列::<双> pt;
pt.push_back(2.3123);
pt.push_back(4.3445);
pt.push_back(1.343);
pt.push_back(4.3445);
pt.push_back(4.3445);
pt.push_back(2.3123);

std :: deque< double> jt;
jt.push_back(4.3445);
jt.push_back(2.3123);

if(isEqual< double>(jt [idx],pt [kdx]))
我自己的版本(用我自己的比较器 - isEqual)效果最好。
正确吗?

template <class T> inline bool isEqual( const T& a, const T& b,
const T epsilon = std::numeric_limits<T>::epsilon() )
{
const T diff = a - b;
return ( diff <= epsilon ) && ( diff >= -epsilon );
}

That epsilon is the difference of 1 and the least value strictly greater
than 1. If you take 1000000 and the least value strictly greater than
1000000, than you will see, that the difference is greater than
epsilon. I don''t think you want those values to make isEqual return
false.


int main()
{
std::deque<double> pt ;
pt.push_back ( 2.3123 );
pt.push_back ( 4.3445 );
pt.push_back ( 1.343 );
pt.push_back ( 4.3445 );
pt.push_back ( 4.3445 );
pt.push_back ( 2.3123 );
std::deque<double> jt ;
jt.push_back ( 4.3445 );
jt.push_back ( 2.3123 );
if ( isEqual<double>( jt [ idx ], pt [ kdx ] ) ) my own version ( with my own comparator - isEqual) works best.
Correct?




几乎,不要滥用epsilon。您的输入值似乎是小数点后的
到小数点后的4位数,所以取1e-4而不是epsilon。你需要将epsilon作为参数添加到isEqual,作为模板

参数通过一些旁路,或者在函数参数中,或硬编码

epsilon其他方式。


Bernd Strieder



Almost, just don''t abuse epsilon. Your input values seem to be rounded
to 4 digits after decimal point, so take 1e-4 instead of epsilon. You
will have to add epsilon as parameter to isEqual, either as template
argument via some bypass, or in the function argument, or hardcode
epsilon some other way.

Bernd Strieder


这篇关于理智检查 - 浮点比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆