RooFit包允许我导入一些TTree分支,但是它将这些分支中包含的值限制在RooRealVar设置的最小值和最大值之间。
RooRealVar t1("t1", "Some variable", 0.0, 1.0);
RooDataSet data("data", "My Dataset", RooArgSet(t1), Import(*myttree));
只要TTree myttree
包含一个分支t1
,这一切都很好,直到你开始接近范围内的浮点值,我的特殊问题发生是因为我有一个像t1
这样的变量,它Map到一个指数分布的变量,我试图拟合这个分布,但是对于t1 ~ 0.0
的值,拟合失败。我的解决方案是稍微更改范围,以截断树中t1
的存储值实际上为零或接近零的潜在事件(下面的代码都是在ROOT解释器中运行的,但我已经确认它在编译代码中也能正常工作):
root[0] RooRealVar t1("t1", "Some variable", 0.001, 1.0);
但是,请注意以下恼人的行为:
root[1] t1 = 0.000998;
root[2] t1.getVal();
(double) 0.0010000000
// this is correct, as 0.000998 < 0.001 so RooFit set it as the lower limit
root[3] t1 = 0.000999;
root[4] t1.getVal();
(double) 0.00099900000
// this is incorrect.
是的,在第二种情况下打印了额外的零,我也不明白,但我最关心的是无法识别0.000999 < 0.001
。当我稍后在if语句中比较这些值时,我发现C++可以区分它们。这里的所有内容似乎都是双精度的,我一直在跟踪代码,看看精度错误似乎出现在哪里。如果我错了,请纠正我,但是浮点数仍然应该保持这些数字达到比较精度,这是怎么回事?,如果这是浮点错误问题,解决它的最好方法是什么?,我有几个事件的值是t1 = 0.000999874
,把边界改成0.0001
也没什么用,仍然有事件在这个边界上。
编辑:我想强调的是,虽然这可能是一个浮点问题,但它真的不应该是。例如,下面的代码是有效的:
root[0] RooRealVar t1("t1", "Some variable", 0.001, 1.0);
root[1] t1 = 0.000999;
root[2] t1.getVal() < 0.001;
(bool) true
1条答案
按热度按时间amrnrhlw1#
好了,各位,我找到了答案(我讨厌这个答案)。它实际上与浮点运算几乎没有关系,老实说,我不知道为什么代码是这样写的。从确定一个值是否“在范围内”的源代码来看:
正如我们在这里所看到的,RooFit * 实际上并不 * 检查
min < val < max
甚至min <= val <= max
,而是min - 1e-6 < value < max + 1e-6
!我找不到一个地方明确地记录了这一点,但我更关心的是inRange
有一个单独的实现,它接受变量名(或逗号分隔的变量名列表),并返回与先前实现不兼容的结果:在这里,我们可以看到创建了一个
epsilon = 1e-8 * fabs(val)
,而不是第一个定义中给出的任意1e-6
。这个比较使用了<=
,而不是<
。应该注意的是,当以这种方式导入时,用于过滤树的方法使用了第一个实现(源代码在这里)。在这个过程中的某个地方(我不完全确定具体在哪里),这些任意的比较导致了下面的矛盾行为:
我会把这归类为bug。在任何情况下,
0.00099900000
都不应该被归类为在(0.001 - 1)
的范围内,而0.00099999999
不是!