以下功能是查找n
1^3 + 2^3 + ... + (n-1) ^3 + n^3 = m
的数字findNb :: Integer -> Integer
findNb m = findNb' 1 0
where findNb' n m' =
if m' == m then n - 1
else if m' < m then findNb' (n + 1) (m' + n^3)
else -1
。这个功能有可能针对速度进行优化吗?
main = print (findNb2 152000000000000000000000)
我知道使用数学公式有更快的解决方案。
我问的原因是JavaScript / C#中的类似实现似乎比Haskell快得多。我只是好奇它是否可以优化。谢谢。
使用ghc -o testo2.exe -O2 -prof -fprof-auto -rtsopts pileofcube.hs
:
使用 -O2 进行编译并进行性能分析:ghc -o testo22.exe -O2 pileofcube.hs
。以下是分析报告的总时间:
总时间= 0.19 秒(190毫秒)(190个滴答@ 1000 us,1个处理器)
使用-O2进行编译但不进行性能分析:Measure-Command {./testo22.exe}
。在powershell中使用function findNb(m) {
let n = 0;
let sum = 0;
while (sum < m) {
n++;
sum += Math.pow(n, 3);
}
return sum === m ? n : -1;
}
var d1 = new Date();
findNb(152000000000000000000000);
console.log(new Date() - d1);
运行它。结果是:
毫秒: 157
代码:
static void Main(string[] args)
{
BigInteger m = BigInteger.Parse("152000000000000000000000");
var s = new Stopwatch();
s.Start();
long n = 0;
BigInteger sum = 0;
while (sum < m)
{
n++;
sum += BigInteger.Pow(n, 3);
}
Console.WriteLine(sum == m ? n : -1);
s.Stop();
Console.WriteLine($"Escaped Time: {s.ElapsedMilliseconds} milliseconds.");
}
结果:在同一台计算机上的Chrome中运行 45 毫秒
正如@Berji和@Bakuriu评论的那样,与上面的JavaScript版本相比,这是不公平的,因为它使用了双精度浮点数,甚至无法给出正确的答案。所以我用C#实现了它,这里是代码和结果:
$builder
->add('information', 'textarea', array(
'label' => false,
'required' => true,
'constraints' => [
new NotBlank()
],
'placeholder' => 'support.contact.titleplaceholder',
));
结果:转义时间: 457 毫秒。
Haskell版本比C#更快...
我在开始时错了,因为我没有意识到由于我的JavaScript知识不足,JavaScript使用了双精度浮点数。
此时似乎问题再没有意义......
答案 0 :(得分:6)
Haskell也可以使用Double
在更短的时间内得到错误的答案:
% time ./so
./so 0.03s user 0.00s system 95% cpu 0.038 total
Javascript也可以通过安装big-integer
和使用bigInt而不是Double来获得正确的结果:
% node so.js
^C
node so.js 35.62s user 0.30s system 93% cpu 38.259 total
......或者它可能并不像那样微不足道。
答案 1 :(得分:4)
确实有一个公式可以让你在恒定时间(而不是n次迭代)中计算它。由于我不记得学校的确切公式,我做了一些搜索,现在是:https://proofwiki.org/wiki/Sum_of_Sequence_of_Cubes。
在haskell代码中,这将转换为
// THIS WILL GIVE YOU CRASH.
ComponentName receiver = new ComponentName(context, NotificationPublisher.class);
我认为应该更快。
答案 2 :(得分:0)
不确定该算法的这个措辞是否更快,但试试这个吗?
findNb :: Integer -> Integer
findNb m = length $ takeWhile (<=m) $ scanl1 (+) [n^3 | n <- [1..]]
(但在未定义的情况下,这有不同的语义。)