首页 > 解决方案 > JavaScript 中更高的精度

问题描述

我正在尝试在 JavaScript 中使用更高精度的数字进行计算,以便能够更多地放大 Mandlebrot 集。(经过一定程度的缩放后,由于精度低,结果会“像素化”)

我看过这个问题,所以我尝试使用 BigNumber 之类的库,但速度慢得无法使用。我一直在尝试解决这个问题,我认为唯一的方法是使用慢速库。

有更快的图书馆吗?

有没有其他方法可以计算更高精度的数字?

有没有其他方法可以放大 Mandlebrot 集?

可能不需要添加此代码,但这是我用来检查点是否在 Mandlebrot 集中的函数。

function mandelbrot(x, y, it) {
    var z = [0, 0]
    var c1 = [x, y]
    
    for (var i = 0; i < it; i++) {
        z = [z[0]*z[0] - z[1]*z[1] + c1[0], 2*z[0]*z[1] + c1[1]]
        if (Math.abs(z[0]) > 2, Math.abs(z[1]) > 2) {
            break
        }
    }
    return i
}

标签: javascriptmandelbrot

解决方案


关键不是 JavaScript 数字的原始数字精度(尽管这当然有其影响),而是基本的 Mandelbrot “转义”测试的工作方式,特别是阈值迭代计数。为了计算复平面中的一个点是在集合内还是在集合外,您一遍又一遍地迭代该点的公式(我不完全记得,也不想查找),直到显然该点在达到迭代阈值之前发散(公式从复平面的原点“逃脱”很多)或不发散。

渲染集合视图时的迭代阈值,该视图覆盖复平面原点周围的大部分视图(从原点向所有方向大约 2 个单位)可以低至 500,以便在现代计算机上的合理放大倍数。但是,当您放大时,迭代阈值需要与复平面上的“窗口”大小成反比增加。如果没有,那么“逃逸”测试就不能以足够的精度在更高的放大倍率下描绘出精细的细节。

我在 JavaScript 实现中使用的公式是

maxIterations = 400 * Math.log(1/dz0)

其中dz0是(任意)平面上窗口的宽度。当放大到集合的视图时(嗯,集合的“边缘”,事情很有趣),dz0变得非常小,因此迭代阈值上升到数千。

当然,对于“逃逸”的点(即属于 Mandelbrot 集的点)的迭代计数可以用作一种“距离”测量。在几次迭代内逃脱的点显然不是“接近”集合,而仅在 2000 次迭代后逃脱的点更接近。该距离质量可以在可视化中以各种方式使用,或者提供颜色值(常见),或者如果集合被渲染为 3D 视图(其中集合作为一种“台面”),则可能提供 z 轴值三个维度和边界是一个垂直的“悬崖”两侧)。


推荐阅读