【问题标题】:How to test if a function grows logarithmically?如何测试函数是否以对数方式增长?
【发布时间】:2013-06-03 23:15:26
【问题描述】:

我的模型中有计算用户得分的函数:

def score
  (MULTIPLER * Math::log10(bets.count * summary_value ** accuracy + 1)).floor
end

我的意思是测试它是否以对数方式增长?

【问题讨论】:

  • 只是为了澄清这个问题:你想测试变量 bets.count 中的函数分数是否为 O(log(n)) 吗?不确定我是否理解。
  • 我想检查函数返回值在bets.count的变量中是否呈对数增长。
  • 如果你想证明分析,这是一道数学题,题外话。如果你想用数字证明,你可以使用一个图表 gem,比如 rplot,并且没有建设性 - 你可以保存这个问题,编辑它并证明我错了。
  • 第二次需要澄清你是想“测试”还是“证明”。另外,您尝试过什么,或者您拒绝了哪些想法?我的意思是,您通常知道如何测试事物,是吗?你为什么不能把它应用到这个上?
  • 我知道如何测试,但我不知道如何通常测试该函数以对数方式增长。我不想针对确切的价值进行测试,而是针对它的增长进行测试。

标签: ruby rspec tdd bdd


【解决方案1】:

一般来说,查看函数是否增长的最好方法是在图表上绘制一些数据。只需使用一些绘图 gem 并评估结果。

对数函数总是如下所示:


(来源:sosmath.com

然后,您可以通过参数调整它的增长速度,并重新绘制图表,直到您对结果感到满意为止。

【讨论】:

  • 我知道如何选择适合我的常数,但我需要测试没有人将其更改为非对数。
【解决方案2】:

测试的目的不是证明它总是有效(这是静态类型/证明的区域),而是检查它是否可能有效。这通常足够好。我猜你是为游戏做的,以及如何确保该功能不会“增长”过快。

我们可以这样做的一种方法是尝试多个值,并检查它们是否遵循一般的对数模式。

例如,考虑一个纯对数函数f(x) = log(x)(任意底):

如果f(x) = y,那么f(x^n) = f(x) * n

所以,如果f(x^n) == (f(x) * n),那么函数是对数的。

将其与线性函数进行比较,例如f(x) == x * 2f(x^n) = x^n * 2,即x^(n - 1) 倍(大得多)。

您可能有一个更复杂的对数函数,例如f(x) = log(x + 7) + 3456。不过,这种模式仍然成立,只是不太准确。所以我所做的是:

  1. 尝试使用x = 1 计算常数值
  2. 找出差异f(x^n) - f(x) * n
  3. f((x*100)^n) - f(100x) * n的绝对差值

如果 (3)/(2) 小于 10,则几乎可以肯定它不是线性的,并且可能是对数的。 10 只是一个任意数字。大多数线性函数的差异将超过 10 亿倍。即使像sqrt(x)这样的函数也会有比10更大的差异。

我的示例代码将只让score 方法接受一个参数,并针对它进行测试(为简单起见+我没有您的支持代码)。

require 'rspec'
require 'rspec/mocks/standalone'

def score(input)
    Math.log2(input * 3 + 1000 * 3) * 3 + 100 + Math.sin(input)
end

describe "score" do
    it "grows logarithmacally based on input" do
        x = 50
        n = 8
        c = score(1)

        result1 = (score(x ** n) - c) / ((score(x) -c) * n)
        x *= 100
        result2 = (score(x ** n) - c) / ((score(x) -c) * n)
        (result2 / result1).abs.should be < 10

    end
end

【讨论】:

    【解决方案3】:

    如果您需要将此函数视为一个黑盒,唯一真正的解决方案是获取一堆值,并查看它们的曲线是否可以很好地近似为对数曲线,重点关注大n。如果您可以对其设置合理的界限,例如 a log(n) &lt; score(n) &lt; b log(n) 用于某些值 ab 那么您可以检查一下。

    【讨论】:

      【解决方案4】:

      虽然我几乎忘记了复杂的数学知识,但似乎事实并不能阻止我回答这个问题。

      我的建议如下

      describe "#score" do
        it "grows logarithmically" do
          round_1 = FactoryGirl.create_list(:bet, 10, value: 5).score
          round_2 = FactoryGirl.create_list(:bet, 11, value: 5).score
          # Then expect some math relation between round_1 and round_2, 
          # calculated by you manually.
        end
      end
      

      【讨论】:

        猜你喜欢
        • 2021-10-12
        • 2014-12-29
        • 1970-01-01
        • 2020-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-26
        相关资源
        最近更新 更多