【发布时间】:2011-09-17 15:47:00
【问题描述】:
我正在谈论使用的算法将允许您向它呈现 x 个项目,每个项目的范围为 a 到 b,结果为 y。我想要一个算法,当呈现出所描述的值时,它会输出它发生的可能性。
例如,对于两个骰子。因为我已经认识他们了(因为可能的结果太低了)。它会告诉你每一种可能性。
设置将类似于。 x=2 a=1 b=6。如果您想知道它产生 2 的机会。那么它只会吐出 1/36(或它的浮点值)。如果你把 7 作为总和,它会告诉你 6。
所以我的问题是,有没有一种简单的方法可以通过已经编写好的算法来实现这样的事情。或者是否必须遍历每个项目的每一次迭代才能获得每个值的组合总数。
确切的公式还可以为您提供从 1 到 12 的每个值的组合。
因此,它会为您提供一个分布数组,其中包含每个索引处的每个组合。如果是0-12。那么 0 有 0,1 有 0,2 有 1。
我觉得这是其他人已经遇到并想要解决的问题类型,并且算法已经完成。如果有人有一种简单的方法来做到这一点,而不仅仅是循环遍历所有可能的值,那就太棒了。
我不知道我为什么要解决这个问题,但由于某种原因,我今天有一种想要解决它的感觉。因为我一直在谷歌搜索,并使用 wolfram alpha,并亲自尝试过。我认为是时候认输并询问社区了。
我希望算法在 c 中,或者 PHP 中(尽管我不希望它不是,因为它慢得多)。使用 c 的原因仅仅是因为我想要原始速度,并且我不想处理类或对象。
伪代码或 C 是显示您的算法的最佳方式。
编辑:
另外,如果我因为数学问题而冒犯了他名字中带有“b”的人,我很抱歉。因为我没有冒犯的意思,但我只想声明 我 不明白。但答案可能会一直留在那里,因为我确信有人可能会提出这个问题并了解其背后的数学原理。
我也无法决定我想用哪种方式编写代码。我想我会尝试同时使用这两种方法,然后决定我更喜欢在我的小图书馆中看到/使用哪一种。
我忘了说的最后一件事是,微积分大约是五年前的四。我对概率、统计和随机性的理解来自我自己通过查看代码/阅读维基百科/阅读书籍的学习。
如果有人好奇是什么引发了这个问题。我有一本书,我正在推迟阅读,名为The Drunkards Walk,当我说 XKCD 904 时,我决定是时候开始阅读它了。然后两天前,当我要睡觉的时候……我思考了如何通过一个简单的算法来解决这个问题,并且能够想到一个。
我对代码的编码理解来自于修补其他程序,看看我破坏某些东西时会发生什么,然后在查看内置函数的文档时尝试我自己的东西。我确实通过阅读维基百科(尽可能多的)理解大 O 符号,伪代码是因为它与 python 非常相似。我自己,不能写伪代码(或者说大学老师)。我不断收到诸如“让它不像真正的代码让它更像伪代码”这样的笔记。那件事没有改变。
编辑 2:以防任何搜索此问题的人都很快想要代码。我已经把它包括在下面了。它是在 LGPLv3 下获得许可的,因为我确信存在此代码的闭源等效项。
它应该是相当可移植的,因为它完全是用 c 编写的。如果想将它变成用 c 编写的各种语言中的任何一种的扩展,那么这样做应该花费很少的精力。我选择“标记”第一个链接到“Ask Dr. Math”作为答案,因为它是我用于这个问题的实现。
第一个文件名为“sum_probability.c”
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
/*!
* file_name: sum_probability.c
*
* Set of functions to calculate the probabilty of n number of items adding up to s
* with sides x. The question that this program relates to can be found at the url of
* http://stackoverflow.com/questions/6394120/
*
* Copyright 2011-2019, Macarthur Inbody
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Lesser GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*
* 2011-06-20 06:03:57 PM -0400
*
* These functions work by any input that is provided. For a function demonstrating it.
* Please look at the second source file at the post of the question on stack overflow.
* It also includes an answer for implenting it using recursion if that is your favored
* way of doing it. I personally do not feel comfortable working with recursion so that is
* why I went with the implementation that I have included.
*
*/
/*
* The following functions implement falling factorials so that we can
* do binomial coefficients more quickly.
* Via the following formula.
*
* K
* PROD (n-(k-i))/i
* i=1;
*
*/
//unsigned int return
unsigned int m_product_c( int k, int n){
int i=1;
float result=1;
for(i=1;i<=k;++i){
result=((n-(k-i))/i)*result;
}
return result;
}
//float return
float m_product_cf(float n, float k){
int i=1;
float result=1;
for(i=1;i<=k;++i){
result=((n-(k-i))/i)*result;
}
return result;
}
/*
* The following functions calculates the probability of n items with x sides
* that add up to a value of s. The formula for this is included below.
*
* The formula comes from. http://mathforum.org/library/drmath/view/52207.html
*
*s=sum
*n=number of items
*x=sides
*(s-n)/x
* SUM (-1)^k * C(n,k) * C(s-x*k-1,n-1)
* k=0
*
*/
float chance_calc_single(float min, float max, float amount, float desired_result){
float range=(max-min)+1;
float series=ceil((desired_result-amount)/range);
float i;
--amount;
float chances=0.0;
for(i=0;i<=series;++i){
chances=pow((-1),i)*m_product_cf(amount,i)*m_product_cf(desired_result-(range*i)-1,amount)+chances;
}
return chances;
}
这是我在上一个文件中所说的显示实现的文件。
#include "sum_probability.c"
/*
*
* file_name:test.c
*
* Function showing off the algorithms working. User provides input via a cli
* And it will give you the final result.
*
*/
int main(void){
int amount,min,max,desired_results;
printf("%s","Please enter the amount of items.\n");
scanf("%i",&amount);
printf("%s","Please enter the minimum value allowed.\n");
scanf("%i",&min);
printf("%s","Please enter the maximum value allowed.\n");
scanf("%i",&max);
printf("%s","Please enter the value you wish to have them add up to. \n");
scanf("%i",&desired_results);
printf("The total chances for %i is %f.\n", desired_results, chance_calc_single(min, max, amount, desired_results));
}
【问题讨论】:
-
绝对不是。我今天醒来,脑子里有这个问题。但我想让它高效。就像前几天,我在 PHP 中完全重写了 prng,以便它使用更好的熵源并生成分布更均匀的数字。你有没有因为想以某种方式找到答案而发痒?请告诉我,你还没有达到不再随机寻求新知识的地步。
-
哈哈,你本来可以拒绝的。只是有些学生试图寻找捷径。我的坏:)
-
如果你对这类问题感兴趣,你可能想看看 prolog。
-
我从来都不是那种用非常简短的语句陈述事情的人。我通常有说太多而不是说不够的问题。我可以想象人们会在这里尝试做类似的事情。
-
@Micheal 我会调查的。这只是我对事物的随机问题之一。它每天都在变化。有些日子,我什至不从事我的个人项目。几天前,它是关于编译器如何处理大于其限制的数字数据类型。我发现这只是通过模数完成的“整数溢出”。大多数时候我可以通过搜索 wikipedia/google 和这里找到它。
标签: c algorithm probability