在C++中,我有一个保证,对于任何给定float a
和float b
,唯一的一个a < b
,a == b
而且a > b
是真的吗?
如果这在编译器和平台之间有所不同,我对x86上的Visual C++感兴趣.
众所周知,在比较浮点值时必须小心.通常,==
我们使用一些基于epsilon或ULP的相等测试来代替使用.
但是,我想知道,有什么案例,使用时==
完全没问题吗?
看看这个简单的片段,哪些案例可以保证成功?
void fn(float a, float b) {
float l1 = a/b;
float l2 = a/b;
if (l1==l1) { } // case a)
if (l1==l2) { } // case b)
if (l1==a/b) { } // case c)
if (l1==5.0f/3.0f) { } // case d)
}
int main() {
fn(5.0f, 3.0f);
}
Run Code Online (Sandbox Code Playgroud)
注意:我已经检查了这个和这个,但它们不包括(全部)我的情况.
注2:似乎我必须添加一些加号信息,所以答案在实践中很有用:我想知道:
这是我在目前的标准草案中找到的唯一相关陈述:
浮点类型的值表示是实现定义的.[注意:本文档对浮点运算的准确性没有要求; 另见[support.limits]. - 结束说明]
那么,这是否意味着甚至"案例a)"是实现定义的?我的意思是,l1==l1
绝对是一个浮点运算.那么,如果一个实现是"不准确的",那么可能l1==l1
是假的?
我认为这个问题不是重复的浮点数==永远好吗?.这个问题没有解决我提出的任何案件.同一主题,不同的问题.我想特别针对案例a)-d)得到答案,因为我无法在重复的问题中找到答案.
c++ floating-point precision language-lawyer floating-point-comparison
这是测试程序:
void testFunc()
{
double maxValue = DBL_MAX;
double slope = std::numeric_limits<double>::quiet_NaN();
std::cout << "slope is " << slope << std::endl;
std::cout << "maxThreshold is " << maxValue << std::endl;
std::cout << "the_min is " << std::min( slope, maxValue) << std::endl;
std::cout << "the_min is " << std::min( DBL_MAX, std::numeric_limits<double>::quiet_NaN()) << std::endl;
}
int main( int argc, char* argv[] )
{
testFunc();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在Debug中,我得到:
slope is nan
maxThreshold is 1.79769e+308
the_min is nan
the_min is 1.79769e+308
Run Code Online (Sandbox Code Playgroud)
在发布中,我得到:
slope …
Run Code Online (Sandbox Code Playgroud) 测试isTRUE(all.equal(x, y))
和identical(x, y)
?之间有什么区别吗?
帮助页面说:
不要在'if'表达式中直接使用'all.equal' - 如果合适,使用'isTRUE(all.equal(....))'或'same'.
但"如果合适的话"让我怀疑.我如何确定哪两个合适?
为什么不起作用1.0 = 2.0
?是不是真正的平等类型?
它给出了错误:
Error: operator and operand don't agree [equality type required]
operator domain: ''Z * ''Z
operand: real * real
in expression:
1.0 = 2.0
Run Code Online (Sandbox Code Playgroud)为什么模式中的实数不会像这样工作?
fun fact 0.0 = 1.0
| fact x = x * fact (x - 1.0)
Run Code Online (Sandbox Code Playgroud)
它给出了错误:
Error: syntax error: inserting EQUALOP
Run Code Online (Sandbox Code Playgroud)我最近开始接触 Python,因为 C++ 很有趣,但 Python 似乎有点酷。只要输入在某个数字范围之间,我就想让 Python 做一些事情。
def main():
grade = float(input("“What’s your grade?”\n:"))
if grade >= 90:
print("“You’re doing great!”")
elif(78 >= grade <= 89):
print("“You’re doing good!”")
elif(77 >= grade > 65):
print("You need some work")
else:
print("Contact your teacher")
main()
Run Code Online (Sandbox Code Playgroud)
当我在做 elif 语句时问题就出现了,我不能这样做,所以只要成绩在 65 到 89 之间,Python 只会打印“做得很好”的语句。你将如何处理数字范围?
python if-statement between numeric-ranges floating-point-comparison
与 Catch2 中的近似零进行比较的规范方法是什么?
我发现这种方式的容差为 1e-12,但目前尚不清楚这是最好的方式:
TEST("a approx. equal to b", "[test]"){
REQUIRE( a - b == (0_a).margin(1e-12) );
}
Run Code Online (Sandbox Code Playgroud)
我不是在问如何比较浮动。我知道这不是一个简单的问题。我问的是如何使用 Catch2 给定事先已知的特定容差。
以下内容不起作用,因为相对(epsilon)错误在零附近表现不佳:
TEST("a approx. equal to b", "[test]"){
REQUIRE( a - b == (0_a).epsilon(1e-5) );
}
Run Code Online (Sandbox Code Playgroud)
其他可能的(不太好)(替代方案似乎是
TEST("a approx. equal to b", "[test]"){
REQUIRE( std::abs( a - b ) < 1e-12 );
}
Run Code Online (Sandbox Code Playgroud)
TEST("a approx. equal to b", "[test]"){
REQUIRE_THAT( a - b, WithinULP(0., ???));
}
Run Code Online (Sandbox Code Playgroud)
TEST("a approx. equal to b", "[test]"){
REQUIRE_THAT( a, WithinULP(b, ???));
}
Run Code Online (Sandbox Code Playgroud) 假设我有这门课:
public class Student
{
long studentId;
String name;
double gpa;
// Assume constructor here...
}
Run Code Online (Sandbox Code Playgroud)
我有一个类似的测试:
List<Student> students = getStudents();
Student expectedStudent = new Student(1234, "Peter Smith", 3.89)
Assert(students.contains(expectedStudent)
Run Code Online (Sandbox Code Playgroud)
现在,如果 getStudents() 方法将 Peter 的 GPA 计算为类似于 3.8899999999994,那么该测试将失败,因为 3.8899999999994 != 3.89。
我知道我可以对单个双精度/浮点值做一个容忍度的断言,但是有没有一种简单的方法可以使这个与“包含”一起工作,这样我就不必单独比较 Student 的每个字段(我将编写许多类似的测试,而我将要测试的实际类将包含更多字段)。
我还需要避免修改有问题的类(即学生)以添加自定义相等逻辑。
此外,在我的实际课程中,将有其他 double 值的嵌套列表需要进行容差测试,如果我必须单独断言每个字段,这将使断言逻辑更加复杂。
理想情况下,我想说“请告诉我此列表是否包含该学生,对于任何浮点/双精度字段,请以 .0001 的容差进行比较”
感谢任何保持这些断言简单的建议。
java floating-point collections unit-testing floating-point-comparison
我希望用float_cmp::approx_eq
(例如)完成所有浮点比较,但继续使用相等比较运算符==
。我该如何实现这一目标?
impl PartialEq for f32 {
fn eq(&self, other: &Self) -> bool {
approx_eq!(f32, *self, *other)
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
error[E0119]: conflicting implementations of trait `std::cmp::PartialEq` for type `f32`
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
Run Code Online (Sandbox Code Playgroud) operator-overloading comparison-operators rust floating-point-comparison
当我运行以下Perl单线程时:
$ perl -e 'print "Oh no!\n" unless 1835 == 100*18.35'
Run Code Online (Sandbox Code Playgroud)
我明白了
Oh no!
这是为什么?