我正在尝试实现三角法的范围缩小操作。但相反,我认为对输入数据执行模数pi / 2操作可能会更好。我想知道什么算法存在并且对于32位IEEE 754浮点的操作有效?
我必须在汇编中实现它,因此只有一条指令我无法使用fmod,除法,乘法等。我的处理器使用16位字,我实现了32位浮点加法,减法,乘法,除法,平方根,余弦和正弦。我只需要范围缩减(模数)来输入余弦和正弦值。
答案 0 :(得分:16)
我认为标准库的fmod()
将是大多数情况下的最佳选择。这是关于几个简单算法的讨论的link。
在我的计算机上,fmod()
使用优化的内联汇编代码(/usr/include/bits/mathinline.h
):
#if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
__inline_mathcodeNP2 (fmod, __x, __y, \
register long double __value; \
__asm __volatile__ \
("1: fprem\n\t" \
"fnstsw %%ax\n\t" \
"sahf\n\t" \
"jp 1b" \
: "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
return __value)
#endif
因此它实际上使用专用CPU指令(fprem)进行计算。
答案 1 :(得分:14)
也许我在这里忽略了这一点,但是 你有什么反对简单地使用fmod吗?
double theta = 10.4;
const double HALF_PI = 2 * atan(1);
double result = fmod(theta, HALF_PI);
答案 2 :(得分:8)
您想要的算法,将浮点value
限制在0
和某些模数n
之间:
Double fmod(Double value, Double modulus)
{
return value - Trunc(value/modulus)*modulus;
}
例如pi mod e
(3.14159265358979 mod 2.718281828459045)
3.14159265358979 / 2.718281828459045 = 1.1557273497909217179 Trunc(1.1557273497909217179) = 1 1.1557273497909217179 - 1 = 0.1557273497909217179 0.1557273497909217179 * e = 0.1557273497909217179 * 2.718281828459045 = 0.42331082513074800
pi mod e = 0.42331082513074800
答案 3 :(得分:0)
精确db.collection("drivers").aggregate([
{
$project: {
_id: {
$toString: "$_id",
},
agent_email: "$agent_email"
},
},
{
$lookup: {
from: "reviews",
localField: "_id",
foreignField: "driver_id",
as: "driver_info",
},
},
// Makes the driver info flat with other information
{
"$unwind": "$driver_info"
},
{
// Now you can group them
$group: {
_id: "$_id",
// Calculates avg on rating field
avg: {
"$avg": "$driver_info.rating"
},
// To make email field appear in next pipeline.
// You can do it for other fields too like Name, etc
agent_email: {
$first: "$agent_email"
}
}
},
{
$project: {
// select the fields you want to display
agent_email: 1,
avg: 1
},
},
])
是用长除法实现的。确切的余数始终可以表示,因为被除数和除数共享相同的格式。您可以研究glibc和musl等开源实现。我也在metallic中取得了一个。 (无耻的插头)
Payne–Hanek范围缩小适用于π等常数除数,我们预先存储了其倒数。因此,此处不适用。