Google BigQuery中的框架

问题描述 投票:2回答:4

我需要在Google BigQuery中计算变量的阶乘-是否有为此功能?我在这里的文档中找不到一个:

https://cloud.google.com/bigquery/query-reference#arithmeticoperators

我目前建议的解决方案是计算数字1到100的阶乘并将其作为表上传并与该表联接。如果您有更好的东西,请提出建议。

由于上下文可能揭示最佳解决方案,因此阶乘用于计算随机变量(时间窗口中的事件数)的泊松概率。参见此处的第一个方程式:https://en.wikipedia.org/wiki/Poisson_distribution

sql google-bigquery factorial
4个回答
4
投票

尝试以下。快速而肮脏的示例

select number, factorial 
FROM js(
// input table
(select number from
(select 4 as number),
(select 6 as number),
(select 12 as number)
),
// input columns
number,
// output schema
"[{name: 'number', type: 'integer'},
{name: 'factorial', type: 'integer'}]",
// function
"function(r, emit){
  function fact(num)
  {
      if(num<0)
       return 0;
      var fact=1;
      for(var i=num;i>1;i--)
        fact*=i;
      return fact;
   }

  var factorial = fact(r.number)

  emit({number: r.number,  factorial: factorial});
}"
)

1
投票

如果直接方法适用于所需的值,则需要计算泊松分布,然后冷却。如果达到极限或无法获得准确的结果,请继续阅读以进行数值分析。

通常,如果对数进行算术运算,然后将exp()作为最终运算,则将获得更好的范围和数值稳定性。

  1. 您想要:c ^ k / k! exp(-c)。
  2. 计算其对数ln(c ^ k / k!exp(-c)),即k ln(x)-ln(k!)-c
  3. 使用exp()。>
  4. 但是,如何在不计算k!的情况下得到ln(k!)?有一个函数叫做gamma函数,在这里的实际要点是它的对数gammaln()可以直接近似,而ln(k!)= gammaln(k + 1)。

    Phil Mainwaring的answer here中有一个Javascript gammaln(),我尚未测试过,但是假设它可以工作,那么它应该适合您的UDF。

将米哈伊尔的答案扩展为对于从1到n的所有数字计算阶乘的正确答案,其中n <500,以下解决方案成立并且可以有效地进行计算:

select number, factorial 
FROM js(
// input table
(
  SELECT
    ROW_NUMBER() OVER() AS number, 
    some_thing_from_the_table
  FROM
    [any table with at least LIMIT many entries]
  LIMIT
    100 #Change this to any number to compute factorials from 1 to this number
),
// input columns
number,
// output schema
"[{name: 'number', type: 'integer'},
{name: 'factorial', type: 'float'}]",
// function
"function(r, emit){
  function fact(num)
  {
      if(num<0)
       return 0;
      var fact=1;
      for(var i=num;i>1;i--)
        fact*=i;
      return fact;
   }

  #Use toExponential and parseFloat to handle large integers in both Javascript and BigQuery
  emit({number: r.number,  factorial: parseFloat(fact(r.number).toExponential())});
}"
)

您最多可以起床27!使用SQL UDF。大于该值的NUMERIC类型将发生溢出错误。

CREATE OR REPLACE FUNCTION factorial(integer_expr INT64) AS ( (
    SELECT
      ARRAY<numeric>[ 
      1,
      1,
      2,
      6,
      24,
      120,
      720,
      5040,
      40320,
      362880,
      3628800,
      39916800,
      479001600,
      6227020800,
      87178291200,
      1307674368000,
      20922789888000,
      355687428096000,
      6402373705728000,
      121645100408832000,
      2432902008176640000,
      51090942171709440000.,
      1124000727777607680000.,
      25852016738884976640000.,
      620448401733239439360000.,
      15511210043330985984000000.,
      403291461126605635584000000.,
      10888869450418352160768000000.][
    OFFSET
      (integer_expr)] AS val ) );

  select factorial(10);

0
投票

将米哈伊尔的答案扩展为对于从1到n的所有数字计算阶乘的正确答案,其中n <500,以下解决方案成立并且可以有效地进行计算:


0
投票

您最多可以起床27!使用SQL UDF。大于该值的NUMERIC类型将发生溢出错误。

© www.soinside.com 2019 - 2024. All rights reserved.