Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 解决浮点舍入问题C++;_C++_Scientific Computing_Matrix Multiplication_Floating Point Precision - Fatal编程技术网

C++ 解决浮点舍入问题C++;

C++ 解决浮点舍入问题C++;,c++,scientific-computing,matrix-multiplication,floating-point-precision,C++,Scientific Computing,Matrix Multiplication,Floating Point Precision,我开发了一个科学应用程序(模拟染色体在细胞核中移动)。染色体分成小片段,使用4x4旋转矩阵绕随机轴旋转 问题是,模拟执行了数千亿次旋转,因此浮点舍入错误累积并呈指数增长,因此随着时间的推移,片段往往会“浮动”并与染色体的其余部分分离 我使用双精度C++。该软件目前在CPU上运行,但将为CUDA移植,模拟最多可以持续1个月 我不知道我如何能以某种方式重新规范化染色体,因为所有片段都链接在一起(你可以把它看作一个双链表),但我认为如果可能的话,这将是最好的主意 你有什么建议吗?我觉得有点失落 多谢各

我开发了一个科学应用程序(模拟染色体在细胞核中移动)。染色体分成小片段,使用4x4旋转矩阵绕随机轴旋转

问题是,模拟执行了数千亿次旋转,因此浮点舍入错误累积并呈指数增长,因此随着时间的推移,片段往往会“浮动”并与染色体的其余部分分离

我使用双精度C++。该软件目前在CPU上运行,但将为CUDA移植,模拟最多可以持续1个月

我不知道我如何能以某种方式重新规范化染色体,因为所有片段都链接在一起(你可以把它看作一个双链表),但我认为如果可能的话,这将是最好的主意

你有什么建议吗?我觉得有点失落

多谢各位

H

编辑: 添加了一个简化的示例代码。 您可以假设所有矩阵数学都是经典的实现

// Rotate 1000000 times
for (int i = 0; i < 1000000; ++i)
{
    // Pick a random section start
    int istart = rand() % chromosome->length;

    // Pick the end 20 segments further (cyclic)
    int iend = (istart + 20) % chromosome->length;

    // Build rotation axis
    Vector4 axis = chromosome->segments[istart].position - chromosome->segments[iend].position;
    axis.normalize();

    // Build rotation matrix and translation vector
    Matrix4 rotm(axis, rand() / float(RAND_MAX));
    Vector4 oldpos = chromosome->segments[istart].position;

    // Rotate each segment between istart and iend using rotm
    for (int j = (istart + 1) % chromosome->length; j != iend; ++j, j %= chromosome->length)
    {
        chromosome->segments[j].position -= oldpos;
        chromosome->segments[j].position.transform(rotm);
        chromosome->segments[j].position += oldpos;
    }
}
//旋转1000000次
对于(int i=0;i<1000000;++i)
{
//选择一个随机段开始
int istart=rand()%染色体->长度;
//进一步拾取末端20段(循环)
int iend=(istart+20)%染色体->长度;
//构建旋转轴
向量4轴=染色体->片段[istart]。位置-染色体->片段[iend]。位置;
axis.normalize();
//建立旋转矩阵和平移向量
矩阵4旋转(轴,rand()/浮动(rand_MAX));
Vector4 oldpos=染色体->片段[istart]。位置;
//使用rotm在istart和iend之间旋转每个段
对于(int j=(istart+1)%chromose->length;j!=iend;++j,j%=chromose->length)
{
染色体->片段[j].位置-=oldpos;
染色体->片段[j].位置.变换(rotm);
染色体->片段[j].位置+=oldpos;
}
}

编写公式,使timestep
T
的数据不完全来自timestep
T-1
中的浮点数据。尽量确保浮点错误的产生仅限于一个时间步


如果没有更具体的问题要解决,很难说得更具体。

我认为这取决于您使用的编译器

VisualStudio编译器支持/fp开关,该开关指示浮点操作的行为


你可以。基本上,/fp:strict是最苛刻的模式

我想这取决于所需的精度,但您可以使用基于“整数”的浮点数。使用这种方法,您可以使用整数并为小数位数提供自己的偏移量

例如,如果精度为4个小数点,则

浮点值->整数值 1.0000 -> 10000 1.0001 -> 10001 0.9999->09999

在进行乘法和除法运算时必须小心,在应用精度偏移时也必须小心。另一方面,您可以快速获得溢出错误


1.0001*1.0001变为10001*10001/10000

问题描述相当模糊,因此这里有一些相当模糊的建议

备选案文1:

找到一些约束集,以便(1)它们应该始终保持不变,(2)如果它们失败,但只是,很容易调整系统,使其保持不变,(3)如果它们都保持不变,则您的模拟不会变得非常疯狂,(4)当系统开始疯狂时,约束开始失败,但只是略微失败。例如,也许染色体相邻位之间的距离最多应该是d,对于某些d,如果其中一些距离略大于d,那么你可以(例如)从染色体的一端沿着染色体走,通过将下一个片段移向它的前一个片段来修复过大的距离,以及它的所有继任者。或者别的什么

然后经常检查约束条件,以确保任何违规行为在被抓获时仍然很小;当你发现违规行为时,就把事情解决。(您可能应该安排,当您解决问题时,您“完全满足”了约束。)

如果一直检查约束比较便宜,那么当然可以这样做。(这样做还可以使您以更低廉的成本进行修复,例如,如果这意味着任何违规行为总是很小的话。)

备选案文2:

找到一种描述系统状态的新方法,使问题不可能出现。例如,也许(我对此表示怀疑)您可以为每对相邻的片段存储一个旋转矩阵,并强制它始终为正交矩阵,然后让片段的位置由这些旋转矩阵隐式确定

备选案文3:


不要将约束视为约束,而是提供一些小的“恢复力”,这样当某件事情偏离了方向时,它就会朝着它应该的方向拉回。注意,当没有任何错误时,恢复力为零或至少可以忽略不计,以便它们不会比原始数值错误更严重地干扰结果。

您需要为系统找到一些约束条件,并努力将其保持在合理的范围内。我做了一系列的分子碰撞模拟,在这些系统中,总能量是守恒的,所以每一步我都会仔细检查系统的总能量,如果它变化了一些阈值,那么我知道我的时间步长选择不当(太大或太小),我选择一个新的时间步长并重新运行它。这样我就可以实时跟踪系统发生的情况

对于这个模拟,我不知道你们有什么守恒量,但若你们有一个守恒量,你们可以试着保持不变。请记住,减小时间步长并不一定能提高精度,您需要根据您的精度优化步长。我已经进行了数周的数值模拟
t0 (x0,y0)
t1 (x0,y0) + (dx,dy) -> (x1, y1)
t2 (x1,y1) + (dx,dy) -> (x2, y2)
t3 (x2,y2) + (dx,dy) -> (x3, y3)
t4 (x3,30) + (dx,dy) -> (x4, y4)
...
t0 (x0, y0) (0, 0)
t1 (x0, y0) (0, 0) + (dx, dy) -> (x0, y0) (dx1, dy1)
t2 (x0, y0) (dx1, dy1) + (dx, dy) -> (x0, y0) (dx2, dy2)
t3 (x0, y0) (dx2, dy2) + (dx, dy) -> (x0, y0) (dx3, dy3)