在使用double fmod(double x, double y)和y是一个整数时,结果似乎总是精确的.
(这是y一个完全确切的数字,int在这里不是意思.)
也许C不要求 fmod()提供这些选择的情况下一个确切的答案,但我试过编译器,结果是准确的,即使当商x/y是不能准确地表示.
y是整数时,是否预期确切的答案? 例子:
double x = 1e10;
// x = 10000000000
printf("%.50g\n", fmod(x, 100));
// prints 0
x = 1e60;
// x = 999999999999999949387135297074018866963645011013410073083904
printf("%.50g\n", fmod(x, 100));
// prints 4
x = DBL_MAX;
// x = 179769313486231570...6184124858368
printf("%.50g\n", fmod(x, 100));
// prints 68
x = 123400000000.0 / 9999;
// x = 12341234.1234123408794403076171875
printf("%.50g %a\n", fmod(x, 100), …Run Code Online (Sandbox Code Playgroud) 请考虑以下代码:
// Filename fputest.cpp
#include <cmath>
#include <cstdio>
int main()
{
double x;
*(__int64 *) &x = 0xc01448ec3aaa278di64; // -5.0712136427263319
double sine1 = sin(x);
printf("%016llX\n", sine1);
double sine2;
__asm {
fld x
fsin
fstp sine2
}
printf("%016llX\n", sine2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用Visual C++ 2012(cl fputest.cpp)编译并执行程序时,输出如下:
3FEDF640D8D36174
3FEDF640D8D36175
Run Code Online (Sandbox Code Playgroud)
问题:
现代FPU用什么方法来计算超越函数?
例如,英特尔CPU提供指令,例如FSIN,FCOS,FYL2X等我很好奇,什么样的算法将用于实际的硬件实现这些.
我天真的猜测是泰勒系列可能与一些查找表相结合,但这只不过是一个疯狂的猜测.请赐教.
PS这个问题比英特尔硬件更普遍.
我一直在研究如何计算正弦和余弦。我找到了一些“标准”方法,包括查找表、CORDIC 算法和泰勒级数。我还发现大多数现代处理器都有一个汇编指令来计算三角函数。我想知道的是这些命令是如何工作的。
所以,我的问题是:当前的处理器使用什么特定算法来计算正弦和余弦?
我有一些代码执行许多日志tan和cos双打操作.我需要这个尽可能快.目前我使用的代码如
#include <stdio.h>
#include <stdlib.h>
#include "mtwist.h"
#include <math.h>
int main(void) {
int i;
double x;
mt_seed();
double u1;
double u2;
double w1;
double w2;
x = 0;
for(i = 0; i < 100000000; ++i) {
u1 = mt_drand();
u2 = mt_drand();
w1 = M_PI*(u1-1/2.0);
w2 = -log(u2);
x += tan(w1)*(M_PI_2-w1)+log(w2*cos(w1)/(M_PI_2-w1));
}
printf("%f\n",x);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用gcc.
有两种明显的方法可以加快速度.首先是选择更快的RNG.第二是加快先验功能.
要做到这一点,我想知道
fcos为cos和fptan的tan.)在英特尔优化手册说
如果不需要使用80位的扩展精度来评估超越函数,则应用程序应考虑使用基于软件的替代方法,例如使用插值技术的基于查找表的算法.通过选择所需的数值精度和查找表的大小,并利用SSE和SSE2指令的并行性,可以通过这些技术提高超越性能. …
在这个链接中,我们可以看到System.Math类的源代码.但我找不到正弦定义的源代码.
这里有什么我想念的吗?
可能的重复:
C 如何计算 sin() 和其他数学函数?
我很好奇如何sin以及cos如何在低水平上实施。
我刚刚查看了 math.h 内部,找不到sin和 的声明cos。但由于这对我来说是一条死胡同,所以我转向你,所以。
我想知道计算正弦需要多少次操作以及使用什么技巧来加速。它们在不同硬件上的实现方式是否不同,是否有处理器支持本机指令?例如,与添加相比,它们的速度有多快?
谢谢!
我不能使用C ++函数sin(),并cos()因引起的PS3 3.40 SDK编译器的某些问题。sin()&的计算是什么,cos()所以我可以在不需要的情况下使用函数math.h?
到目前为止,我已经想出了这些,但它们似乎无法正常运行?
float sin(float deg) {
bool neg = false;
while (deg >= 360) deg = deg - 360;
while (deg < 0) deg = deg + 360;
if (deg > 180) {
deg = deg - 180;
neg = true;
}
float ret = (float)(4*deg*(180-deg))/(40500-(deg*(180-deg)));
if (neg)return ret*-1;
return ret;
}
float cos(float AnglesDeg)
{
float AnglesRad = DegreesToRadians(AnglesDeg);
float Rad = (float)(PI/2.0f)-AnglesRad;
float ang = …Run Code Online (Sandbox Code Playgroud) 为了节省调用性能sin,并处理整数角度(更便于操作和保存),而不是使用浮点作为角度,我正在构建一个sin查找函数,其中 4096 个单位等于 2pi 弧度。为了节省内存,我只存储前 1024 个 sin 值,它们相当于sin( [0, pi/2) ).
static const float SinTable[1024] = {0, 0.00153398, ..., 0.999995, 0.999999};
Run Code Online (Sandbox Code Playgroud)
为了处理第三象限和第四象限的角度,我简单地有条件地否定:
return Angle&2048 ? -UnsignedSin : UnsignedSin;
Run Code Online (Sandbox Code Playgroud)
UnsignedSin查找到的 sin 值位于 之间的位置[0, 2048)。但我该如何处理第二象限和第四象限呢?如何通过检查角度是否位于第二或第四象限(例如 )[0, 1)来有条件地正确映射 存储的 sin 值?我尝试了这个,但这不太正确,因为角度的结果是 0.999999 而不是它应该是的 1。[1, 0)Angle&10241024
const float UnsignedSin = SinTable[(Angle&1024 ? ~A : A)&1023];
Run Code Online (Sandbox Code Playgroud)
1 的值永远不会存储在 sin 表中,所以我假设 a1-SinTable[...]是必需的?但我不能完全正确地理解它。
我尝试计算双精度浮点值的反正切,该值保存在 xmm 寄存器中。对于正常的浮点,可以使用旧的 x87 指令 FPATAN,但是如何使用 double 来做到这一点?