以科学记数法将小(1.0E-12)数字存储为双精度数

Posted

技术标签:

【中文标题】以科学记数法将小(1.0E-12)数字存储为双精度数【英文标题】:Storing small (1.0E-12) numbers as doubles in scientific notation 【发布时间】:2013-03-07 16:45:46 【问题描述】:

设置如下:

对于我的学士论文,我想测试 LHC 使用的喷射算法。基本上第一步是以下:给定一些 4 动量

p[0] = nullvector(45.0000000000106,33.03951484238976,14.97124733712793,26.6317895033428)

我想通过以 10^(-12) 的顺序将一些(例如 50 个)随机生成的 4 向量添加到最后三个分量来模拟实验数据,这样它们就很小(这就是有趣的物理学发生的地方),但明显高于 15 位小数的双浮点精度。因此,快速而肮脏的解决方案如下:

seed=time(NULL);
srand(seed);
random=(rand()%9001)*1.0E-15;
random=random+1E-12;
printf("%.15E\n",random);

这给了我 1E-12 和 10E-12 (=1E-11) 之间的随机数,最多三位小数,所以在“真实”双打中,这给了我 15 位小数。

现在重点:我可以在不超过双浮点精度的情况下按小数点后三位以上的顺序存储数字吗?

PS:有没有更好的方法来生成小的随机数? (这听起来像是另一个话题;))

【问题讨论】:

【参考方案1】:

创建浮点随机数的传统方法是通过取 double x = (double)rand()/RAND_MAX; 使其成为范围 [0-1) - 然后乘以 9001E-1 将范围缩放到 1E-121E-15 值 [包括零]。

【讨论】:

很好,谢谢!有没有关于为什么“传统方法”使用整数除法而不是模数的读物? 对不起,错过了将除法的一侧转换为浮动...正如您指出的那样,模将创建一个整数(在您的情况下,在 0..9001 范围内,然后将其相乘使它更小,但它在很大程度上只给出 3 个小数位。除法方法确实给出了更大范围的分数,因为 RAND_MAX 通常为 2^31-1,这有可能产生大量小数位“填写”。 我明白了,通过类型转换,事情是一致的并解决了小数问题:) 干杯! 此外,在许多传统的 rand() 实现中,低位没有很好的熵——它们通常是循环的,所以通过整数除法可以获得更好的结果(即使你只想要一个0-10 整数) rand 中使用余数至少存在三个问题:它丢弃了一些位(Mats Petersson 上面提到过),生成器的熵很差(Frederick Cheung 上面提到过),以及分布不均匀(高达RAND_MAX%YourQuotient 的残基比其他残基出现的频率高 1/RAND_MAX)。

以上是关于以科学记数法将小(1.0E-12)数字存储为双精度数的主要内容,如果未能解决你的问题,请参考以下文章

如何避免以科学记数法表示的双精度数和数字的字符串到数字转换?

#mysql# 在mysql 的float的科学计算法存储,希望保留数的精度

为啥我不能将数字转换为双精度数?

以更易读的格式显示双精度科学记数法

C#将数字四舍五入为双精度数的任意数字[重复]

在java中将十六进制数字字符串转换为双精度数字