在很多情况下,我不仅需要正弦,而且需要相同参数的余弦。
对于C,sincos
通用unix m
数学库中有该函数。实际上,至少在i386上,这应该是一条汇编指令fsincos
。
sincos,sincosf,sincosl-同时计算sin和cos
我猜这些好处存在是因为在计算正弦和余弦时存在明显的重叠:sin(x)^2 + cos(x)^2 = 1
。但是AFAIK尝试将其快捷方式化为并没有用cos = Math.sqrt(1 - sin*sin)
,因为该sqrt
功能的费用与此相似。
有什么方法可以在Java中获得相同的好处吗?我想我要为此付出代价double[]
。由于增加了垃圾回收,这可能使所有工作变得毫无意义。
还是Hotspot编译器足够聪明,足以识别出我需要两者,并将其编译成sincos
命令?我可以测试它是否可以识别它,并且可以例如通过确保Math.sin
和Math.cos
命令在我的代码中直接连续来帮助它识别它?从Java语言的角度来看,这实际上是最有意义的:让编译器对其进行优化以使用fsincos
程序集调用。
从一些汇编器文档中收集:
Variations 8087 287 387 486 Pentium
fsin - - 122-771 257-354 16-126 NP
fsincos - - 194-809 292-365 17-137 NP
Additional cycles required if operand > pi/4 (~3.141/4 = ~.785)
sqrt 180-186 180-186 122-129 83-87 70 NP
fsincos
应该需要一个额外的弹出声,但是应该在1个时钟周期内出现。假设CPU也没有对此进行优化,sincos
则其速度应该几乎是调用sin
两次的速度的两倍(第二次计算余弦;因此我认为它需要做一个加法运算)。sqrt
在某些情况下可能会更快,但正弦可能会更快。
更新
:我已经在C语言中做了一些实验,但是还没有定论。有趣的是,sincos
似乎甚至略高于是sin
(无cos
),以及GCC编译器将使用fsincos
,当你同时计算sin
和cos
-所以它做什么,我想热点做(或做热点,太?)。fsincos
除了不使用之外,我还无法阻止编译器使我胜过我cos
。然后它会回落到一个C
sin
,没有fsin
。
我用卡尺进行了一些微基准测试。在(预先计算的)随机数数组(-4 * pi .... 4 * pi)上进行10000000次迭代。我尽了最大的努力来获得最快的JNI解决方案-
很难预测您是否会真正得到fsincos
仿真sincos
。报告的数字是10项卡尺试验中最好的一项(依次包括3到10次试验,报告了平均值)。大约每个内循环运行30-100次。
我已经对几种变体进行了基准测试:
Math.sin
仅(参考)Math.cos
仅(参考)Math.sin
+ Math.cos
sincos
通过JNIMath.sin
+通过Math.sqrt( (1+sin) * (1-sin) )
+符号重建cosMath.cos
+通过Math.sqrt( (1+cos) * (1-cos) )
+符号重建实现犯罪(1+sin)*(1-sin)=1-sin*sin
从数学上讲,但是如果sin接近1,它应该更精确吗?运行时差异最小,您节省了一个附加项。
通过进行符号重建x %= TWOPI; if (x<0) x+=TWOPI;
,然后检查象限。如果您有一个想法,如何用更少的CPU来执行此操作,我将很高兴听到。
sqrt
至少对于常见角度而言,数值通孔似乎还可以。从粗略的实验来看,范围为1e-10。
Sin 1,30 ==============
Cos 1,29 ==============
Sin, Cos 2,52 ============================
JNI sincos 1,77 ===================
SinSqrt 1,49 ================
CosSqrt 1,51 ================
在sqrt(1-s*s)
主场迎战sqrt((1+s)*(1-s))
使得约0.01差别。如您所见,sqrt
基于方法的方法胜过其他方法(因为我们目前无法sincos
在纯Java中访问)。JNI
sincos
优于计算sin
和cos
,但是该sqrt
方法仍然更快。cos
本身似乎始终比sick(0,01)更好sin
,但是用于区分符号的大小写区分需要额外的>
测试。我不认为我的研究结果支持,要么sin+sqrt
或cos+sqrt
明显preferrable,但他们节省约的40%的时间相比,sin
然后cos
。
如果我们将Java扩展为具有 固有的优化sincos
,那么可能会更好。恕我直言,这是一个常见的用例,例如在图形中。当在AWT,蜡染等中使用时,许多应用程序都可以从中受益。
如果再次运行它,我还将添加JNI sin
和一个noop
以估计JNI的成本。也许还可以sqrt
通过JNI
对这个技巧进行基准测试。只是为了确保我们确实希望sincos
从长远来看具有内在性。
问题内容: 我有一个使用100%Java编写的大型现有代码库,但是我想在它的一些新部分中使用Python。我需要进行一些文本和语言处理,而我宁愿使用Python和类似NLTK的库来执行此操作。 我知道Jython项目,但这似乎代表了一种从Python内部使用Java及其库的方法,而不是相反的方式-我对此是否错? 如果没有,那么在Java和Python之间进行交互的最佳方法是什么,这样(理想情况下)
问题内容: 这可能是一个新手问题,但希望您能帮助我。:)我有这样的事情: 我使用的是NetBeans IDE,由于某种原因,在弯曲的行中加了下划线的是printStackTrace。当我按Alt + Enter时,提示应删除Throwable.printStackTrace()。这是什么意思?谁能提供更多的见解,这可能意味着什么?还是我可以忽略这个? 谢谢! 问题答案: 这只是一个建议。在ecli
问题内容: 您必须使用Java做什么才能获得Runtime.exec()来运行路径上的程序?我正在尝试运行已放入路径(/ usr / local / bin)的gpsbabel。 问题答案: 它将从Java进程继承路径。因此,无论Java进程具有什么环境,生成的进程也都将具有。检查环境的方法如下: 您设置了 并 导出了吗?如果不导出,则子进程将无法使用它。 此外,您 必须同时 使用stdout和s
问题内容: 请提供一些有关如何在Google Guice或Java EE中使用的基本信息,如果使用简单的代码进行解释将非常有帮助,在此先感谢您 问题答案: 的目的在吉斯是允许你绑定类和实例以通用类型(与指定类型的参数)避免从一个事实,即泛型未用Java物化,即,从这样的事实而产生的问题,即擦除皮之间的差和在运行。通过创建泛型类型的 临时 子类,允许泛型参数的值在擦除后幸存下来。 示例用法: 这会将
我有一个关于注释在Java中的用法的问题。 根据我所读到的内容,设置可能返回空值的方法是一个很好的实践。这样,如果使用,IDE可以帮助检测一些空指针异常错误,或者建议删除不必要的空指针异常检查。 到目前为止还不错,但是对于方法参数使用怎么样?这是一个好的实践吗?还是代码会变得更加冗长(如果与一起使用),而且可能会失去好处,因为您并不总是知道将向函数调用传递什么参数?另外,您对在setter方法中使
我在java中使用Arraylists时遇到了问题,我的代码如下所示: 我将相同的数字添加到列表中,但是当我试图像这样比较列表中索引0的数字时,布尔值的结果是false,而它应该是true: 为false 但是当我使用一些临时变量,然后比较它们时,它给出了我所期望的,在bcompare上的真实值: 为true 我在这里做错了什么?