我正在尝试熟悉CGAL精确数型,在这个过程中,我尝试实现一个函数来计算两个确切数字的除法的浮点余数(如std::fmod()
)。但是,我想知道如何在平凡的operator+
、-
、*
、/
之外做任何精确的数字运算。在搜索文档一段时间之后,我找到了CGAL::div()
和CGAL::mod()
,但它们不起作用(返回CGAL::Null_tag
?)似乎是因为它们只为EuclideanRing
定义。示例代码:
#include <iostream>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Number = Kernel::FT;
int main() {
Number a(2.5);
Number b(1.5);
std::cout << CGAL::div(a, b) << "\n"; // error
}
编译错误:
/tmp/cgal-test/test.cpp: In function ‘int main()’:
/tmp/cgal-test/test.cpp:9:15: error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘CGAL::Null_functor::result_type’ {aka ‘CGAL::Null_tag’})
9 | std::cout << CGAL::div(a, b) << "\n"; // error
| ~~~~~~~~~ ^~ ~~~~~~~~~~~~~~~
| | |
| | CGAL::Null_functor::result_type {aka CGAL::Null_tag}
| std::ostream {aka std::basic_ostream<char>}
当然,计算浮点余数的一个简单解决方案是对结果使用CGAL::to_double()
和计算std::fmod()
,但这可能会失去精度或溢出,因此这将首先否定使用精确数字类型的好处。另一种方法是重复减法,但是如果a
大而b
小的话,这会增加运行时间。
有人能解释一下(或者指给我看相关的文档,解释一下)以准确的方式实现这样的操作的目的是什么吗?
发布于 2022-07-31 07:59:25
您的代码为我编译,但它打印1.66667
,而我希望您想要1
?如果我定义了CGAL_USE_GMPXX=1
或CGAL_DO_NOT_USE_BOOST_MP=1
,我确实会得到一个类似的错误,因此这个错误取决于内部用于精确理性主义的类型。还有一个函数integral_division
。
我能想到的最简单的方法是计算a/b
并将其转换为确切的整数类型:CGAL::Exact_integer(CGAL::exact(a/b))
(使用<CGAL/Exact_integer.h>
,尽管可能有一种更简洁的方法来获取与此rational类型相对应的整数类型,可能是Get_arithmetic_kernel
)。也许转换可以用NT_converter
或Coercion_traits
.无论如何,这个圆圈的方向可能取决于数字类型,所以你应该检查你得到的符号,并可能修正商1。
Number q(CGAL::Exact_integer(CGAL::exact(a/b)));
std::cout << q << ' ' << (a-b*q) << '\n';
我们从来不需要这样的理性操作,这就解释了为什么我们没有在CGAL中实现它。
https://stackoverflow.com/questions/72951953
复制