我想了解什么是机器epsilon.根据维基百科,它可以计算如下:
def machineEpsilon(func=float):
machine_epsilon = func(1)
while func(1)+func(machine_epsilon) != func(1):
machine_epsilon_last = machine_epsilon
machine_epsilon = func(machine_epsilon) / func(2)
return machine_epsilon_last
Run Code Online (Sandbox Code Playgroud)
但是,它仅适用于双精度数字.我有兴趣修改它以支持单精度数字.我读过numpy可以用,尤其是numpy.float32课堂.有人可以帮忙修改功能吗?
http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx
如果创建一个自定义算法来确定是否可以将两个浮点数视为相等,则必须使用大于Epsilon常量的值来确定两个值相等的可接受的绝对差值.(通常,差异幅度比Epsilon大很多倍.)
那么这不是真正可以用于比较的ε吗?我真的不明白MSDN的措辞.
它可以在这里的示例中用作epsilon吗?- 浮动和双重比较最有效的方法是什么?
最后这看起来非常重要,所以我想确保我有一个可靠的实现平等,大于,小于,小于或等于,大于或等于.
在Python中是否有(或获取方法)epsilon的标准值?我需要比较浮点值,并希望与最小的可能差异进行比较.
在C++中numeric_limits::epsilon( ),提供了一个函数,它为任何给定的数据类型提供epsilon值.Python中有相应的东西吗?
我发现跑步了
Math.Log10(double.Epsilon)
Run Code Online (Sandbox Code Playgroud)
将-324在机器A上返回,但将-Infinity在机器B上返回.
他们最初的表现方式与回归相同-324.
两台机器都使用相同的操作系统(WinXP SP3)和.NET版本(3.5 SP1).机器B上可能有Windows更新,但是不知道发生了什么变化.
什么可以解释行为上的差异?
评论中讨论的更多细节:
Math.Log10(double.Epsilon)在机器B上打印一个简单的控制台应用程序-324,而不是-Infinity0x9001F(读取_controlfp()).更新:最后一点(FPU控制字)不再成立:使用较新版本的_controlfp()显示不同的控制字,这解释了不一致的行为.(有关详细信息,请参阅下面的rsbarro答案.)
为什么Decimal数据类型没有Epsilon字段?
从手册中,decimal值的范围是±1.0×10e-28到±7.9×10e28.
表示
Double大于零的最小正值
所以看起来,Decimal也有这样一个(非平凡的)价值.但为什么不容易获得?
我明白+1.0×10e-28正是最小的正十进制值大于零:
decimal Decimal_Epsilon = new decimal(1, 0, 0, false, 28); //1e-28m;
Run Code Online (Sandbox Code Playgroud)
顺便提一下,有几个问题可以提供有关Decimal数据类型内部表示的信息:
这是一个Epsilon有用的例子.
假设我从一些采样集和所采样本的权重(或计数)之和得到加权值.现在我想计算加权平均值.但我知道权重(或计数)的总和可能仍为零.为了防止除零,我可以做if... else...并检查零.或者我可以像这样写:
T weighted_mean = weighted_sum / (weighted_count + T.Epsilon)
Run Code Online (Sandbox Code Playgroud)
这个代码在我看来更短.或者,或者我可以跳过+ T.Epsilon,而是初始化:
T weighted_count = T.Epsilon;
Run Code Online (Sandbox Code Playgroud)
当我知道实际权重的值永远不会接近时,我就能做到这一点Epsilon.
对于某些数据类型和用例,这可能更快,因为它不涉及分支.据我所知,即使分支很短,处理器也无法将两个分支用于计算.我可能知道零点以50%的速率随机出现:=)对于Decimal,速度方面可能并不重要,甚至在第一种情况下也没有用.
我的代码可能是通用的(例如,生成的),我不想为小数写单独的代码.因此,人们希望看到它Decimal具有与其他实值类型类似的接口.
float有没有办法获得小于 的浮点类型可表示的最大值1。
我看过以下定义:
static const double DoubleOneMinusEpsilon = 0x1.fffffffffffffp-1;
static const float FloatOneMinusEpsilon = 0x1.fffffep-1;
Run Code Online (Sandbox Code Playgroud)
但这真的是我们应该如何定义这些价值观吗?
根据标准,std::numeric_limits<T>::epsilon是机器 epsilon,即 1.0 与浮点类型可表示的下一个值之间的差T。但这并不一定意味着定义T(1) - std::numeric_limits<T>::epsilon会更好。
作为单元测试的一部分,我需要测试一些边界条件.一种方法接受一个System.Double参数.
有没有办法获得下一个最小的双值?(即将尾数减1个单位值)?
我考虑使用,Double.Epsilon但这是不可靠的,因为它只是从零开始的最小增量,因此不适用于较大的值(即9999999999 - Double.Epsilon == 9999999999).
那么所需的算法或代码是什么:
NextSmallest(Double d) < d
Run Code Online (Sandbox Code Playgroud)
......总是如此.
我有一个单元测试,测试边界:
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void CreateExtent_InvalidTop_ShouldThrowArgumentOutOfRangeException()
{
var invalidTop = 90.0 + Double.Epsilon;
new Extent(invalidTop, 0.0, 0.0, 0.0);
}
public static readonly double MAX_LAT = 90.0;
public Extent(double top, double right, double bottom, double left)
{
if (top > GeoConstants.MAX_LAT)
throw new ArgumentOutOfRangeException("top"); // not hit
}
Run Code Online (Sandbox Code Playgroud)
我以为我只是通过添加最小可能的正双倍来向尖端90.0倾斜,但现在异常没有被抛出,任何想法为什么?
在调试时,我看到top为90,当它应该是90.00000000 ....
编辑:
我应该考虑更难,90+Double.Epsilon将失去其解决方案.似乎最好的方法是做一些转移.
解:
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void CreateExtent_InvalidTop_ShouldThrowArgumentOutOfRangeException()
{
var invalidTop = Utility.IncrementTiny(90); // 90.000000000000014
// var sameAsEpsilon = Utility.IncrementTiny(0);
new Extent(invalidTop, 0, 0, 0);
}
/// <summary> …Run Code Online (Sandbox Code Playgroud) 我想,以确定double 机器精度在Java中,使用它是最小的可表示的定义double值,x这样1.0 + x != 1.0,就像在C/C++.根据维基百科,这台机器epsilon等于2^-52(52是double尾数位数 - 1).
我的实现使用了这个Math.ulp()函数:
double eps = Math.ulp(1.0);
System.out.println("eps = " + eps);
System.out.println("eps == 2^-52? " + (eps == Math.pow(2, -52)));
Run Code Online (Sandbox Code Playgroud)
结果是我的预期:
eps = 2.220446049250313E-16
eps == 2^-52? true
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.不过,如果我检查给定的eps确实是最小的 x这样1.0 + x != 1.0,似乎有一个较小的一个,又名先前 double根据价值Math.nextAfter():
double epsPred = Math.nextAfter(eps, Double.NEGATIVE_INFINITY);
System.out.println("epsPred = " + epsPred);
System.out.println("epsPred < eps? " …Run Code Online (Sandbox Code Playgroud) 为了简化问题,我想说我想a / (b - c)在floats 上计算表达式.
为了确保结果是有意义的,我可以检查b和c是相等的:
float EPS = std::numeric_limits<float>::epsilon();
if ((b - c) > EPS || (c - b) > EPS)
{
return a / (b - c);
}
Run Code Online (Sandbox Code Playgroud)
但是我的测试表明,如果可能的话,不能保证有意义的结果,也不能不提供结果.
a = 1.0f;
b = 0.00000003f;
c = 0.00000002f;
Run Code Online (Sandbox Code Playgroud)
结果:不满足if条件,但表达式将生成正确的结果100000008(与浮点数的精度相同).
a = 1e33f;
b = 0.000003;
c = 0.000002;
Run Code Online (Sandbox Code Playgroud)
结果:满足if条件,但表达式不会产生有意义的结果+1.#INF00.
我发现检查结果更可靠,而不是参数:
const float INF = numeric_limits<float>::infinity();
float x = a / (b - c); …Run Code Online (Sandbox Code Playgroud)