十年或两年前,编写数字代码以避免使用乘法和除法并使用加法和减法是值得的.一个很好的例子是使用前向差异来评估多项式曲线,而不是直接计算多项式.
是否仍然如此,或者现代计算机架构已经发展到*,/不再比+慢很多倍, - ?
具体来说,我对在现代典型x86芯片上运行的编译C/C++代码感兴趣,这些代码具有广泛的板载浮点硬件,而不是一个小型微软试图在软件中进行FP.我意识到流水线和其他架构增强功能排除了特定的循环计数,但我仍然希望获得有用的直觉.
更新:Elixir并不慢,我的算法是.我的算法甚至不是苹果对比.有关Ruby和Go等效算法,请参阅下面的Roman答案.还要感谢José,我的慢速算法可以通过添加前缀MIX_ENV = prod来显着加快.我已经更新了问题中的统计数据.
原始问题: 我正在研究多种语言的Project Euler问题,只是为了了解语言的效率和速度.在问题#5中,我们被要求找到可被1到20的所有数字整除的最小正数.
我用多种语言实现了该解决方案.以下是统计数据:
为什么Elixir的表现如此之慢?我尝试在所有语言中使用相同的优化.警告:我是FP和Elixir新手.
我有什么办法可以改善Elixir的表现吗?如果您使用任何分析工具来找出更好的解决方案,请将它们包含在响应中吗?
在Go:
func problem005() int {
i := 20
outer:
for {
for j := 20; j > 0; j-- {
if i%j != 0 {
i = i + 20
continue outer
}
}
return i
}
panic("Should have found a solution by now")
}
Run Code Online (Sandbox Code Playgroud)
在Ruby中:
def self.problem005
divisors = (1..20).to_a.reverse
number = 20 …Run Code Online (Sandbox Code Playgroud) 当使用 numpy 计算A @ a其中A是随机 N × N 矩阵并且 a 是具有 N 个随机元素的向量时,计算时间在 N=100 时会跳跃一个数量级。这有什么特别的原因吗?作为比较,在CPU上使用torch进行相同的操作有更逐渐的增加
用 python3.10 和 3.9 和 3.7 尝试过,具有相同的行为
\n用于生成绘图的 numpy 部分的代码:
\nimport numpy as np\nfrom tqdm.notebook import tqdm\nimport pandas as pd\nimport time\nimport sys\n\ndef sym(A):\n return .5 * (A + A.T)\n\nresults = []\nfor n in tqdm(range(2, 500)):\n for trial_idx in range(10):\n A = sym(np.random.randn(n, n))\n a = np.random.randn(n) \n \n t = time.time()\n for i in range(1000):\n A @ a\n …Run Code Online (Sandbox Code Playgroud) 我在Clojure中实现了一些基本的复数运算,并注意到它比大致相当的Java代码慢了大约10倍,即使是类型提示也是如此.
相比:
(defn plus [[^double x1 ^double y1] [^double x2 ^double y2]]
[(+ x1 x2) (+ y1 y2)])
(defn times [[^double x1 ^double y1] [^double x2 ^double y2]]
[(- (* x1 x2) (* y1 y2)) (+ (* x1 y2) (* y1 x2))])
(time (dorun (repeatedly 100000 #(plus [1 0] [0 1]))))
(time (dorun (repeatedly 100000 #(times [1 0] [0 1]))))
Run Code Online (Sandbox Code Playgroud)
输出:
"Elapsed time: 69.429796 msecs"
"Elapsed time: 72.232479 msecs"
Run Code Online (Sandbox Code Playgroud)
有:
public static void main( String[] args ) {
double[] z1 …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个计算十进制数字的程序?到1000位数或更多。
为了有趣地进行低级编程,最终程序将以汇编形式编写在没有乘法或除法且仅执行16位加法的8位CPU上。为了简化实现,希望只能使用16位无符号整数运算,并使用迭代算法。速度不是主要问题。快速乘法和除法不在此问题的范围内,因此也不要考虑这些问题。
在进行汇编之前,我仍在尝试在台式计算机上的C语言中找到可用的算法。到目前为止,我发现以下系列相当有效并且相对容易实现。
该公式是使用收敛加速技术从Leibniz系列推导而来的,要推导该公式,请参见Carl D.Offner撰写的《计算?中的数字》(https://cs.umb.edu/~offner/files/pi.pdf) ,第19-26页。最终公式显示在第26页。我编写的初始公式有错别字,请刷新页面以查看固定公式。2第54页中解释了最大术语中的常数项。该白皮书还介绍了一种高级迭代算法,但是我在这里没有使用它。
如果一个人使用许多(例如5000)项来评估该系列,则有可能获得千位数的?。容易,并且我发现使用此算法,该系列也易于迭代评估:
用2填充数组以开始第一次迭代,因此新公式类似于原始公式。
让carry = 0。
从最伟大的任期开始。从数组中获得一项(2),将其乘以PRECISION对进行定点除法2 * i + 1,然后将提示作为新项保存到数组中。然后添加下一项。现在递减i,转到下一学期,重复直到i == 1。最后加上最后一项x_0。
由于使用的PRECISION是16位整数10,因此,将获得2个十进制数字,但只有第一个数字有效。将第二个数字另存为进位。显示第一个数字加进位。
x_0 是整数2,不应为后续迭代添加整数,将其清除。
转到第4步,计算下一个十进制数字,直到获得所需的所有数字为止。
将此算法转换为C:
#include <stdio.h>
#include <stdint.h>
#define N 2160
#define PRECISION 10
uint16_t terms[N + 1] = {0};
int main(void)
{
/* initialize the initial terms */
for (size_t i = 0; i < N …Run Code Online (Sandbox Code Playgroud) c algorithm fixed-point numerical-computing mathematical-expressions
如何用R:求解非方形线性系统A X = B?
(在系统没有解决方案或无限多解决方案的情况下)
示例:
A=matrix(c(0,1,-2,3,5,-3,1,-2,5,-2,-1,1),3,4,T)
B=matrix(c(-17,28,11),3,1,T)
A
[,1] [,2] [,3] [,4]
[1,] 0 1 -2 3
[2,] 5 -3 1 -2
[3,] 5 -2 -1 1
B
[,1]
[1,] -17
[2,] 28
[3,] 11
Run Code Online (Sandbox Code Playgroud) 我正在使用Clojure,我需要运行一个小模拟.我有一个长度为n的向量(n通常在10到100之间),它包含值.在每个模拟轮次(可能一起1000轮)中,矢量中的一个值随机更新.我想我可以通过使用Java数组并调用aset方法来实现这一点,但这会破坏函数式编程/不可变性的习惯用法.
有没有更实用的方法来实现这一点,还是应该使用Java数组?
arrays functional-programming clojure immutability numerical-computing
抱歉,如果愚蠢但无法找到答案.
#include <iostream>
using namespace std;
int main()
{
double a(0);
double b(0.001);
cout << a - 0.0 << endl;
for (;a<1.0;a+=b);
cout << a - 1.0 << endl;
for (;a<10.0;a+=b);
cout << a - 10.0 << endl;
cout << a - 10.0-b << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
0
6.66134e-16
0.001
-1.03583e-13
尝试使用MSVC9,MSVC10,Borland C++ 2010进行编译.所有这些都到达了大约1e-13的错误.只有1000,10000增量才能产生如此显着的误差累积是否正常?
鉴于log(a)和log(b),我想计算log(a+b)(以数字稳定的方式).
我为此写了一个小函数:
def log_add(logA,logB):
if logA == log(0):
return logB
if logA<logB:
return log_add(logB,logA)
return log( 1 + math.exp(logB-logA) ) + logA
Run Code Online (Sandbox Code Playgroud)
我写了一个程序,这是迄今为止最耗时的代码.显然我可以尝试优化它(例如,消除递归调用).
你知道从和计算的标准math或numpy功能吗?log(a+b)log(a)log(b)
如果没有,您是否知道为此函数创建单个C++挂钩的简单方法?它不是一个复杂的函数(它使用浮点数),正如我所说,它占据了我运行时的大部分时间.
在此先感谢,数值方法忍者!
我刚刚遇到了Ruby的NArray库 - 请原谅我这个问题时的无知:)
使用NArray库比标准Ruby Array实现有什么好处?
我已经看到NArray面向数值计算,但是看看API,看起来只有几个扩展而不是数字值 - 没有你不能用Array做的事情.
谷歌并没有真正想出这个问题的有用解释.
参考资料我发现:
http://rubydoc.info/gems/narray-ruby19/0.5.9.7/NArray
arrays ×2
clojure ×2
python ×2
algorithm ×1
c ×1
c++ ×1
elixir ×1
fixed-point ×1
flops ×1
immutability ×1
logarithm ×1
math ×1
mips ×1
narray ×1
numpy ×1
optimization ×1
performance ×1
r ×1
ruby ×1
system ×1
truncation ×1
type-hinting ×1
x86 ×1