Google BigQuery 中的阶乘
Factorial in Google BigQuery
我需要在 Google BigQuery 中计算一个变量的阶乘 - 有这个函数吗?我在此处的文档中找不到:
https://cloud.google.com/bigquery/query-reference#arithmeticoperators
此时我提出的解决方案是计算数字 1 到 100 的阶乘并将其作为 table 上传并与 table 合并。如果大家有更好的,请指教
由于上下文可能会揭示最佳解决方案,因此阶乘用于计算随机变量的泊松概率(window 时间内的事件数)。在这里查看第一个等式:https://en.wikipedia.org/wiki/Poisson_distribution
在下面试试。快速和肮脏的例子
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});
}"
)
将 Mikhail 的答案扩展为通用且正确的计算所有数字 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())});
}"
)
如果直接方法适用于您需要计算泊松分布的值,那么很酷。如果你达到它爆炸的地步或给你不准确的结果,然后继续阅读数值分析的乐趣。
一般来说,如果您对对数进行算术运算,然后将 exp() 作为最终运算,您将获得更好的范围和数值稳定性。
- 你要:c^k/k!指数(-c)。
- 计算其对数,ln( c^k / k!exp(-c) ),
即 k ln(x) - ln(k!) - c
- 取其中的 exp()。
但是我们如何在不计算 k! 的情况下得到 ln(k!)?有个函数叫gamma函数,这里的实用点是它的对数gammaln()可以直接近似,ln(k!) = gammaln(k+1).
Phil Mainwaring 的 answer here 中有一个 Javascript gammaln(),我还没有测试过,但假设它有效,它应该适合你的 UDF。
您最多可以获得 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);
我需要在 Google BigQuery 中计算一个变量的阶乘 - 有这个函数吗?我在此处的文档中找不到:
https://cloud.google.com/bigquery/query-reference#arithmeticoperators
此时我提出的解决方案是计算数字 1 到 100 的阶乘并将其作为 table 上传并与 table 合并。如果大家有更好的,请指教
由于上下文可能会揭示最佳解决方案,因此阶乘用于计算随机变量的泊松概率(window 时间内的事件数)。在这里查看第一个等式:https://en.wikipedia.org/wiki/Poisson_distribution
在下面试试。快速和肮脏的例子
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});
}"
)
将 Mikhail 的答案扩展为通用且正确的计算所有数字 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())});
}"
)
如果直接方法适用于您需要计算泊松分布的值,那么很酷。如果你达到它爆炸的地步或给你不准确的结果,然后继续阅读数值分析的乐趣。
一般来说,如果您对对数进行算术运算,然后将 exp() 作为最终运算,您将获得更好的范围和数值稳定性。
- 你要:c^k/k!指数(-c)。
- 计算其对数,ln( c^k / k!exp(-c) ),
即 k ln(x) - ln(k!) - c - 取其中的 exp()。
但是我们如何在不计算 k! 的情况下得到 ln(k!)?有个函数叫gamma函数,这里的实用点是它的对数gammaln()可以直接近似,ln(k!) = gammaln(k+1).
Phil Mainwaring 的 answer here 中有一个 Javascript gammaln(),我还没有测试过,但假设它有效,它应该适合你的 UDF。
您最多可以获得 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);