带有度数参数的trig函数何时应返回-0.0?


10

在创建三角函数my_sind(d)my_cosd(d)my_tand(d),即使用了度参数,而不是一个弧度一个以90的倍数提供确切的答案,我注意到,结果是有时-0.0不是0.0

my_sind( 0.0) -->  0.0
my_sind(-0.0) --> -0.0

my_sind(180.0) --> -0.0
my_sind(360.0) -->  0.0

sin()并且tan()通常会针对给定的零符号输入返回相同的零符号结果。my_sin()应该sin()为这些输入匹配才有意义。

my_sind( 0.0) alike sin( 0.0) -->  0.0
my_sind(-0.0) alike sin(-0.0) --> -0.0

现在的问题是:什么整数non_zero_n应/可将结果再回到-0.0my_sind(180*non_zero_n)my_cosd(180*n + 180)my_tand(180*non_zero_n)

编写代码很容易,因此只需f(-0.0)生成-0.0并完成即可。简单地想知道是否有任何理由使任何其他 f(x)回报-0.0非零),x以及确保该符号的重要性。


注:这是不是为什么的问题0.0-0.0发生。这不是为什么cos(machine_pi/4)不回来0.0。这也不是如何控制0.0或的生成的问题-0.0。我将其视为设计问题是最好的。

Answers:


4

“最不令人惊讶”的设计原则建议我们参考以前建立的功能进行指导。在这种情况下,最接近的已建立功能由IEEE Std 754-2008(IEEE浮点算法标准)第9节提供sinpicospi引入。这些功能不是当前ISO C和ISO C ++标准的一部分,但已被合并到各种编程平台(例如CUDA)的数学库中。

这些函数计算sin(πx)和cos(πx),其中与π的乘法隐式发生在函数内部。tanpi未定义,但可以根据数学等价假设来提供的功能tanpi(x) = sinpi(x) / cospi(x)

现在,我们可以定义sind(x) = sinpi(x/180)cosd(x) = cospi(x/180)tand(x) = tanpi(x/180)以直观的方式。IEEE-754法术的第9.1.2节进行处理的特殊论点sinpicospi。特别是:

对于正整数n,sinPi(+ n)为+ 0,sinPi(-n)为-0。这意味着在适当的舍入模式下,对于所有x,sinPi(-x)和-sinPi(x)是相同的数字(或均为NaN)。当可表示n +½时,对于任何整数n,cosPi(n +½)为+0。

IEEE 754-2008标准未给出所引用要求的理由,但是相关部分的早期草案指出:

如果函数的值为零,则最好通过考虑数学函数的符号函数的连续扩展来确定该0的符号。

在细读的754工作组邮件归档可能会产生额外的见解,我还没有通过它来挖的时间。实施sind()cosd()tand()如上述那样,我们然后在该表的示例的情况下到达:

SIND
 angle value 
  -540 -0
  -360 -0
  -180 -0
     0  0
   180  0
   360  0
   540  0

COSD
 angle value
  -630  0
  -450  0
  -270  0
   -90  0
    90  0
   270  0
   450  0

TAND
 angle value
  -540  0
  -360 -0
  -180  0
     0  0
   180 -0
   360  0
   540 -0

5

对于给定的零符号输入,sin()和tan()通常返回相同的零符号结果

通常可以这样,因为:

  • 速度/精度。对于足够小的双打,最佳答案sin(x)x。也就是说,对于小于约的数字1.49e-8,最接近x的正弦的实际上是x本身(请参见glibc源代码sin())。

  • 特殊情况的处理

    一些特殊的算术运算会受到零号的影响;例如"1/(+0) = +inf"但是"1/(-0) = -inf"。为了保持其有效性,符号位必须根据从连续性考虑得出的规则,通过某些算术运算传播。

    尽管IEEE标准未指定,但基本先验函数(例如sin(z)和tan(z))及其反函数和双曲线类似物的实现均应遵循类似的规则。的实现sin(z) 有望复制的符号z 及其在的值z = ±O

    复杂的基本功能的分支切割或 W. Kahan 所做的关于无所事事的事情都非常厌恶)

    带负号的零呼应数学分析的概念,即从下面逼近0作为一个单边限制(考虑1 / sin(x):零号有很大的不同)。

编辑

考虑到第二点,我这样写my_sind

my_sind(-0.0) is -0.0
my_sind(0.0) is 0.0

最新的C标准(F.10.1.6 sin和F.10.1.7 tan,带符号0的实现)指定,如果参数为±0则返回原样

编辑2

对于其他值,我认为这只是一个近似问题。给定M_PI<π:

0 = sin(π) < sin(M_PI)  1.2246467991473532e-16  +0.0
0 = sin(-π) > sin(-M_PI)  -1.2246467991473532e-16  -0.0
0 = sin(2*π) > sin(2*M_PI)  -2.4492935982947064e-16
0 = sin(-2*π) < sin(-2*M_PI)  2.4492935982947064e-16

因此,如果my_sind以180°的倍数提供准确的答案,则它可以返回+0.0-0.0(我看不出有比另一个更喜欢的理由)。

如果my_sind使用某种近似值(例如degree * M_PI / 180.0转换公式),则应考虑其接近临界值的方式。


您有什么想法sind(180), sind(-180), sind(360), sind(-360),...
chux-恢复莫妮卡2014年

感谢更新。也许我的帖子不清楚。主要问题是何时不应该my_trig(x)返回?-0.0|x|0.0
chux-恢复莫妮卡2014年

感谢“因此,如果my_sind以180°的倍数提供确切的答案,则它可以返回+0.0或-0.0(我看不出有一个比另一个更喜欢的理由)。” 这是到目前为止最接近的讨论点。我认为,“让您感到惊讶的原则”总是鼓励您返回+0.0,但希望-0.0在某些情况下(除之外x == +/-0.0)是否有令人信服的理由返回。
chux-恢复莫妮卡2014年

@chux:我认为对于的倍数180.0,确实必须检查给定的相对机器精度值。即,最小增量/减量以该数字格式给出了不同的可表示值。然后,将该值与真实值进行比较,看它会落在正侧还是负侧。
rwong 2015年

@rwong感谢您的想法。90.0倍数精确 sind(double degrees)cosd(double degrees)可返回的值:-1.0, +0.0, +1.0。该帖子即将-0.0被寄回(除了sind(-0.0)之外)。注:sind()没有没有使用简单的sin(x/360*M_PI)方法。
chux-恢复莫妮卡

3

该库不会尝试将+0与-0区分开。IEEE 754对这种区别非常担心...我发现[math.h]中的函数很难编写,而不会为无用的迹象感到烦恼。-PJ Plauger,《标准C库》,1992年,第128页。

形式上,触发函数应根据C标准返回零的符号...这将使行为未定义。

面对不确定的行为,最小惊讶原则建议从中复制相应功能的行为math.h。这闻起来是合理的,而与相应功能的行为有所不同,math.h就像一种将错误准确地引入代码(取决于零的符号)的方式。


在三角函数math.h不返回0.0给出当参数等+/- pi / 2之间或+/- pi作为这些功能只能取表示的值接近 +/- PI / 2等。这些“近”值返回接近0.0的结果。由于标准库触发函数(sin cos tan)不会为任何输入(+/- 0.0除外)返回0.0(或-0.0),但是my_sind(),my_cosd(),my_tand()可以返回0.0(或-0.0),因此没有0.0行为可重复。
chux-恢复莫妮卡2014年

@chux sin(-0.0)应该返回的前提-0是可疑的。它将IEEE标准的实现细节视为三角原理。尽管在IEEE实现中存在一个通用的数学原理,即零限制为两个间隔,但它发生在抽象级别上,而不是在常规三角函数内(因此,三角函数返回的内容具有可变性)。可能发生的最好事情是,您可以定义一个任意约定,但是它将与math.h的非平衡点区别于零的符号。
Ben rudgers 2014年

注:我并不认为sin(-0.0)应该返回-0.0,但my_sind(x)应该匹配sin(x)x+/-0.0。IOW:遵循以前的做法。此外,问题本身更多地是关于什么时候该做什么x != 0.0,是否应该像等等一样my_sind(x)返回?也许您的答案/评论解决了这个问题-但我还没有看到。-0.0my_sind(180)
chux-恢复莫妮卡2014年

@chux如果行为是不确定的,则它是不确定的。这就是C的方式。Plauger不担心+0-0他写道math.h二十年前。我不清楚您为差异所苦恼的问题正在解决。
Ben rudgers 2014年

1
希望您看到sin(rad)对于任何值rad>0和任何精度的良好实现都将永远不会产生,0.0因为pi是非理性的。[Ref](www.csee.umbc.edu/~phatak/645/supl/Ng-ArgReduction.pdf)但是,由于值0.0是正确的数学结果,因此每x的倍数都会my_sind(deg)产生一个精确的0.0(+或-)180.0。“最少惊讶的原理”建议在这些情况下返回0.0。我的问题是-0.0在这些情况下应该退货吗?
chux-恢复莫妮卡2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.