You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ double-double扩展精度类浮点编译优化问题

关于Double-Double高精度类在MSVC Release模式下精度丢失的问题

我用C++实现了一个double-double类,通过两个double类型提升数值精度,数值表示为number = hi + lo(实际不会直接计算该和,因为hi + lo == hi)。以下是精简后的代码:

class doubledouble
{
public:
    double hi, lo;

    doubledouble()
    {
        hi = 0.0;
        lo = 0.0;
    }

    doubledouble quickTwoSum(const double a, const double b) const
    {
        int old;
        doubledouble out;
        double s = a + b;
        double e = b - (s - a);
        out.hi = s;
        out.lo = e;
        return (out);
    }

    doubledouble twoSum(const double a, const double b) const
    {
        double s = a + b;
        double v = s - a;
        double e = (a - (s - v)) + (b - v);
        doubledouble out;
        out.hi = s;
        out.lo = e;
        return (out);
    }

    doubledouble operator+(const doubledouble& in) const
    {
        doubledouble s, t;
        s = twoSum(in.hi, this->hi);
        t = twoSum(in.lo, this->lo);
        s.lo += t.hi;
        s = quickTwoSum(s.hi, s.lo);
        s.lo += t.lo;
        s = quickTwoSum(s.hi, s.lo);
        return(s);
    }

    doubledouble split(const double a) const
    {
        const double split = (1 << 12) + 1;
        double t = a * split;
        doubledouble out;
        out.hi = t - (t - a);
        out.lo = a - out.hi;
        return (out);
    }

    doubledouble twoProd(const double a, const double b) const
    {
        double p = a * b;
        doubledouble aS = split(a);
        doubledouble bS = split(b);
        double err = ((aS.hi * bS.hi - p) + aS.hi * bS.lo + aS.lo * bS.hi) + aS.lo * bS.lo;
        aS.hi = p;
        aS.lo = err;
        return (aS);
    }

    doubledouble operator*(const doubledouble& in) const
    {
        doubledouble p;
        p = twoProd(this->hi, in.hi);
        p.lo += this->hi * in.lo + this->lo * in.hi;
        p = quickTwoSum(p.hi, p.lo);
        return(p);
    }
};

这段代码在Debug模式下工作正常,但在Release模式下仅能达到普通double的精度。我使用MSVC编译器,若在类的前后添加#pragma optimize("", off)和对应的on,代码可正常运行但速度极慢。

我原本推测问题出在t - (t - a)这类表达式上——从数学上看它等于a,编译器可能会对其进行优化。为定位问题,我尝试在特定函数前后添加#pragma optimize,但即使给类内所有函数都添加该指令,代码仍无法正常工作。

我的两个问题:

  • 为什么#pragma optimize在类内的特定函数中无效?这对定位问题至关重要。
  • 如何让编译器不对t - (t - a)这类特定表达式进行优化?使用临时变量似乎也会被编译器优化掉。

编辑补充

作为可复现的测试代码,我使用了如下片段:

double a = 1.23456789012345;
const double split = (1 << 12) + 1;
double t = a * split;
double hi = t - (t - a);
double lo = a - hi;
   
std::cout << "hi: " << hi << ", lo: " << lo << std::endl;

Debug和Release模式下的输出均为:

hi: 1.23457, lo: -3.48832e-13

由此可见t - (t - a)似乎不是问题所在。

至于能复现错误行为的“简单”示例——我计算了缩放倍数超过10^14的曼德博集合,Debug模式下结果完美,但Release模式下出现像素化。生成图像的函数如下:

void CalcMandelCPU_doubledouble(std::atomic<unsigned int>* RowCounter)
    {
        std::complex<doubledouble> Z, C;

        int Y = (*RowCounter)++;
        while (Y < ResY)
        {
            for (int X = 0; X < ResX; X++)
            {
                C.real(minX + (X + 0.5) * (maxX - minX) / ResX);
                C.imag(minY + (Y + 0.5) * (maxY - minY) / ResY);

                int i;
                Z = 0;
                for (i = 0; i < MaxIter; i++)
                {
                    Z = Z * Z + C;

                    if (Z.real() * Z.real() + Z.imag() * Z.imag() > 4.0)
                        break;
                }

                if (i == MaxIter)
                {
                    Result[Y * ResX + X] = 0;
                }
                else
                {
                    Result[Y * ResX + X] = i + 1 - log(log(Z.real() * Z.real() + Z.imag() * Z.imag())) / log(2.0);
                }
            }
            Y = (*RowCounter)++;
        }
    }

需定义MaxIter、ResX和ResY,minX、maxX、minY和maxY用于指定缩放后的视图,示例视图变量(均为doubledouble类型):

  • minX.hi = -1.9997740601362948, minX.lo = 9.2915246622385581e-17
  • maxX.hi = -1.9997740601362861, maxX.lo = 7.5150963188138267e-17
  • minY.hi = -3.2900430992572130e-09, minY.lo = 1.7490722630808694e-25
  • maxY.hi = -3.2900375437016574e-09, maxY.lo = 1.0427104313278710e-25

内容的提问来源于stack exchange,提问作者Paul Aner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:44:50