在一些地方,我需要计算下一个值,给定一个N:
double size = 1.0 / Math.Pow(2, N);由于我不会计算N> 15的这个值,所以我想到了以下性能优化:
public static readonly double[] RegionSizes =
{
1, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125,
0.00390625, 0.001953125, 0.000976563, 0.000488281, 0.000244141, 0.00012207, 0.00006103515625, 0.000030517578125
};
//Usage
double size = RegionSizes[N];这是个好办法吗?为什么/为什么不?
发布于 2019-01-19 21:07:28
这不是一个好的解决方案,有几个原因。
1.:您的值不如双数据类型所允许的精确。例如,
1.0 / Math.Pow(2, 12)计算为0.000244140625,而查找值仅为0.000244141。根据下面的计算,这可能会产生很大的不同。
2.您的数组是公共的和可变的。虽然数组引用是只读的(因此不能将新数组分配给引用),但数组本身却不是。例如
RegionSizes[2] = 5;编译和运行,没有任何问题。您(或其他每一个开发人员)可以根据他的意愿覆盖数组中的值。最好使用不可变集合(如ReadOnlyCollection<double> )来防止运行时对缓存值的操作。(如果这是一个有趣的项目,而您是唯一的开发人员,这可能不会成为一个问题;在大于1dev的大型项目中,这种类型的疏忽可能会导致难以跟踪的bug。)
3.经验告诉我们,这样的假设
我不会计算N> 15的这个值
不要总是坚持真理。可以肯定的是,一种更灵活的方法(比如在第一次需要时计算每个值,然后存储它并在需要时再次使用它)将允许更大的灵活性。当然,如果没有任何关于您打算在程序中做什么的信息,就很难判断这是否相关。
4.我强烈怀疑您正在进行过早的优化(因为您没有提到实际的性能问题,也没有提到任何表明浮点操作是造成此类问题的原因的度量)。唐纳德·克努斯
真正的问题是,程序员在错误的地方和错误的时间里花费了太多的时间来担心效率;过早的优化是编程中所有问题(或至少大部分)的根源。
我没什么可补充的。根据我的经验,在>95%的软件项目中,您不需要担心>95%的代码的性能。因此,在进行优化时,您应该遵循以下步骤:
是的,我知道,优化代码很有趣--但是你很快就会迷失方向,花上几百个小时来优化那些根本不需要优化的代码。
发布于 2019-01-19 16:17:14
它可以称为预先计算的本地缓存不可变字段数组。
它很好,而且肯定比每次计算值都要好。
虽然我说不可变,但我并不是说它是深不可变的-所有的值都可以改变,只有数组引用本身是不可变的。如果您需要将它传递给您不完全信任的方法,那么您可以传递一个副本--如果它们混淆了值,那么它就是它们的本地副本。
首先,请确保使用正确的初始值。要做到这一点,您可以使用:https://www.wolframalpha.com/input/?i=N%5B1%2F2%5E(0..15),+15%5D计算它们
N[1/2^(0..15), 15]这将产生价值
{
1.00000000000000,
0.500000000000000,
0.250000000000000,
0.125000000000000,
0.0625000000000000,
0.0312500000000000,
0.0156250000000000,
0.00781250000000000,
0.00390625000000000,
0.00195312500000000,
0.000976562500000000,
0.000488281250000000,
0.000244140625000000,
0.000122070312500000,
0.0000610351562500000,
0.0000305175781250000
}类型double是近似值,最多可信任15个位置,也称为有效数字。计数不是从十进制开始,而是从最高值开始。对于浮点数类型,只有7,小数点是28。这就是为什么我只显示了15位数字。
https://codereview.stackexchange.com/questions/211805
复制相似问题