C++ 在C+中缩放双精度时的精度差异+;

C++ 在C+中缩放双精度时的精度差异+;,c++,double,precision,C++,Double,Precision,是否有必要缩放双值,或者在使用真实值时是否更精确?使用double进行计算以获得最佳精度的最佳范围是什么 也就是说,我定义了一条三次贝塞尔曲线。我应该为三次曲线使用真实世界的位置值,还是应该在计算时使用值的规格化大小,然后在读取真实世界的值时将其放大 我将给出一个示例,看看下面的代码: void CCubic::getTAtDistance(const CCubicPoint& pFrom, const double& distance, double& t) {

是否有必要缩放双值,或者在使用真实值时是否更精确?使用double进行计算以获得最佳精度的最佳范围是什么

也就是说,我定义了一条三次贝塞尔曲线。我应该为三次曲线使用真实世界的位置值,还是应该在计算时使用值的规格化大小,然后在读取真实世界的值时将其放大

我将给出一个示例,看看下面的代码:

void CCubic::getTAtDistance(const CCubicPoint& pFrom, const double& distance, double& t)
{

    CPoint pEnd = getP(t);

    double cLength = (pEnd - pFrom).getLength();
    int compare = GLOBAL::DoubleCompare(cLength, distance);
    if(compare > 0)
    {
        t-=(t - pFrom.t)*0.5;
        getTAtDistance(pFrom, distance, t);
    }
    else if(compare < 0)
    {
        t+=(t - pFrom.t)*0.5;
        getTAtDistance(pFrom, distance, t);
    }//else if
}
void CCubic::getTAtDistance(const CCubicPoint&pFrom、const double&distance、double&t)
{
CPoint pEnd=getP(t);
double cLength=(pEnd-pFrom).getLength();
int compare=GLOBAL::DoubleCompare(长度、距离);
如果(比较>0)
{
t-=(t-pFrom.t)*0.5;
获取距离(pFrom,距离,t);
}
否则如果(比较<0)
{
t+=(t-pFrom.t)*0.5;
获取距离(pFrom,距离,t);
}//否则如果
}
此方法计算三次曲线上与三次曲线上另一点的距离处的点

  • pFrom是计算距离的点
  • 将增量计算t,并定义新的 完成增量后,在曲线上指定距离处的点
  • getP方法计算并返回三次曲线上指定t处的点
最初,当调用该方法时,t设置为1.0(曲线终点)。 由于三次贝塞尔不是线性的,我需要在距离点pFrom的指定距离处递增计算最近的点

用于在曲线上创建所有点的代码如下所示:

void CCubic::initEvenPointList(double distance, double offset)
{
    //TODO: Check if r can be 0 in the 1/r code, and how to handle/show it.
    lPoints.clear();
    minRadius = DBL_MAX;

    double t = 0;
    CCubicPoint ccP = getCubicPoint(t);
    lPoints.push_back(ccP);
    if(ccP.radius<minRadius) minRadius = ccP.radius;

    if(offset>0)
    {
        t = 1.0;
        getTAtDistance(getCubicPoint(0), offset, t);
        ccP = getCubicPoint(t);
        lPoints.push_back(ccP);
        if(ccP.radius<minRadius) minRadius = ccP.radius;
    }//if


    std::cout << "CCubic::initEventPointList -- Starting loop\n";
    while(t<1.0)
    {
        double newT = 1.0;
        getTAtDistance(ccP, distance, newT);
        if(newT>1) break;
        t = newT;
        ccP = getCubicPoint(t);
        lPoints.push_back(ccP);
        if(ccP.radius<minRadius) minRadius = ccP.radius;
    }

    ccP = getCubicPoint(1.0);
    lPoints.push_back(ccP);
    if(ccP.radius<minRadius) minRadius = ccP.radius;


    std::cout << "P(" << 0 << "): t = " << lPoints[0].t << "\n";
    double d = 0;
    for(int i=1; i<lPoints.size(); i++)
    {
        d+= (lPoints[i] - lPoints[i-1]).getLength();
        std::cout << "P(" << i - 1<< "): t = " << lPoints[i].t << ", d = " << d*400 << "\n";
    }//for
}
void CCubic::initEvenPointList(双距离、双偏移)
{
//TODO:检查r在1/r代码中是否可以为0,以及如何处理/显示它。
lPoints.clear();
最小半径=DBL_MAX;
双t=0;
CCubicPoint ccP=getCubicPoint(t);
l点。推回(ccP);
if(ccP半径0)
{
t=1.0;
GetAtDistance(getCubicPoint(0),偏移量,t);
ccP=getCubicPoint(t);
l点。推回(ccP);

if(ccP.radiusA
double
具有11位指数和53位精度。这意味着任何有限的double都具有相同的精度,无论其大小是大约4400或4e300。标准化与“真实”范围与任何其他大小都不重要

需要注意的一点是,如果使用的数字的大小相差很大。例如,在浮点路径中,
1e300+1==1e300
,因为没有足够的精度位来表示
1

我认为这种大小上的差异导致了您的问题。在
双重比较中:

if(abs(A - B) < std::numeric_limits<double>::epsilon()) return 0;
if(abs(A-B)
epsilon
被定义为1.0的最小可表示浮点差。我理解您的目的是考虑浮点误差,但不同的大小将需要不同的相对误差。Bruce Dawson有更多的细节和对其他技术的回顾

(这里使用
abs
也让我有点紧张,因为C中的
abs
只接受整数。因此,是否获得浮点绝对值取决于您包含的头文件,以及您之前是否使用命名空间std;
使用std::abs;
。也许我是只是有点偏执,但我更喜欢C的
fabs
或显式的
std::abs


您的代码不够完整,无法编译,因此我不确定,但我认为使用
DoubleCompare
改进此比较将获得一致的结果。

谢谢,我错过了这一个,fabs!虽然我的迭代似乎太精确了,因为在某种程度上我没有达到epsilon以下。我必须设置“自己的”ε到0.0001,否则我永远不会接近0。我认为这是不可行的,因为这将使我失去精度和“雾”任何无限循环。我还必须在GetAtDistance中重写代码,因为它根本不能最佳工作,在无限循环中很容易下降。但我注意到精度要高得多,但仍然低于实际值,这可能是由我的自定义epsilon造成的。
if(abs(A - B) < std::numeric_limits<double>::epsilon()) return 0;