.NET Forum / Languages / C# / August 2006
Formula calculation C# code needed
|
|
Thread rating:  |
GB - 30 Aug 2006 06:12 GMT Hello, How to calculate value for the following formula (I need C# code):
res = (((m+1)(m+2)...(m+(k-1)))/1.2...(k-1))
or more generalized formula is:
k-1 __ | | (m+i) i=1 res = --------------- k-1 __ | | i i=1
Thanks, GB
Jon Skeet [C# MVP] - 30 Aug 2006 07:14 GMT > Hello, > How to calculate value for the following formula (I need C# code): [quoted text clipped - 12 lines] > | | i > i=1 Well, why not just do the calculation in a loop? Loop round doing the multiplication, then loop round doing the division. You'll lose a fair amount of precision, but that may be okay depending on what your use is...
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
GB - 30 Aug 2006 07:26 GMT Please, give me an example.
GB
>> Hello, >> How to calculate value for the following formula (I need C# code): [quoted text clipped - 17 lines] > amount of precision, but that may be okay depending on what your use > is... Ben Newsam - 30 Aug 2006 09:47 GMT >Please, give me an example. > [quoted text clipped - 15 lines] >>> | | i >>> i=1 Let me get this right...
In your example, say, if m=3 and k=10, and i=1 (is i *always* 1?), then you need to calculate:
(4.5.6.7.8.9) / (1.2.3.4.5.6.7.8.9), which works out at 0.16667 (same as 1/6)
and m=4 and k=9 would be (5.6.7.8)/(1.2.3.4.5.6.7.8), which is 0.041667
If this is correct, then I would do it recursively:
long MyFunc ( long n, long Limit, long i ) { long Result = n; if ( n <= Limit ) return Result; return ( n * MyFunc ( n - i, Limit, i ) ); }
Then you can do:
long k = 10; long m = 3; long i = 1; double res1 = 0.0, res2 = 0.0; double result = 0.0;
res1 = (double) MyFunc(k - 1, m + 1, i); res2 = (double) MyFunc(k - 1, 1, 1); result = res1 / res2;
and k = 9; m = 4; res1 = (double) MyFunc(k - 1, m + 1, i); res2 = (double) MyFunc(k - 1, 1, 1); result = res1 / res2;
The last one gives 0.041666...664 Oh well, it's close.
 Signature Posted via a free Usenet account from http://www.teranews.com
DaanishRumani - 30 Aug 2006 10:44 GMT I would do it this way.
// Numerator double Pi_MplusI(int start, int end, int m) { double result = 1.0;
if(start > end) { // swap start and end int temp = start; start = end; end = temp; }
if(start == end) { // not sure about this!!! return 1.0; }
for(int i= start; i < end; ++i) { result *= m + i; }
return result; }
// Denominator double Pi_I(int start, int end) { double result = 1.0;
if(start > end) { // swap start and end int temp = start; start = end; end = temp; }
if(start == end) { // not sure about this!!! return 1.0; }
for(int i= start; i < end; ++i) { result *= i; }
return result; }
// Result double res(int i, int m) { double result = 1.0; int i; int k; int m;
// get your values here i = 1; k = 10; m = 100;
result = Pi_MplusI(1, k) / Pi_I(1, k);
return result; }
Marc Gravell - 30 Aug 2006 10:59 GMT actually, if my math is right that would be 4.5.6.7.8.9.10.11.12 / 1.2.3.4.5.6.7.8.9, leaving 10.11.12 / 1.2.3, leaving 220 [i is just the product-indexer in the range 1 to k-1 inclusive]
Perhaps the trick here is to look for those terms that are not cancelled; you could probably do this by looking at the figures and doing a lot of thinking, but you'd need to think for each and every formula; how about this instead? It detects cancelled terms before they are multiplied (reducing both rounding error and the FLOP count), and could be applied to any such formula.
Marc
class Product { // dictionary key is the factor, value is the power readonly Dictionary<int, int> factors = new Dictionary<int, int>(); public void Multiply(int factor) { int power; factors.TryGetValue(factor, out power); factors[factor] = power + 1; } public void Divide(int quotient) { int power; factors.TryGetValue(quotient, out power); factors[quotient] = power - 1; } public double Evaluate() { // could also perhaps do with logarithms? double result = 1.0; foreach (KeyValuePair<int, int> pair in factors) { int power = pair.Value; if (power == 0) continue; // nothing to do result *= Math.Pow(pair.Key, power); } return result; }
} static class Program { static void Main() { int k = 10, m = 3; Product p = new Product(); // could actually do both loops at once, but // keep it simple for easy re-use with different // maths... for(int i = 1; i <= k - 1; i++) { p.Multiply(m+i); } for (int i = 1; i <= k - 1; i++) { p.Divide(i); } MessageBox.Show(p.Evaluate().ToString()); } }
Marc Gravell - 30 Aug 2006 11:18 GMT Some refinements below: * handles zero multipliers much more efficiently (short-circuits everything) * throws exception on zero quotients * tracks "sign" separately, so that -17 can cancel 17 * discards "unit" (but tracks sign) * performs single * and / directly, to avoid a Math.Pow() call
Marc
class Product { readonly Dictionary<int, int> factors = new Dictionary<int, int>(); bool zero = false, negate = false; public void Multiply(int factor) { if (zero) return; if (factor == 0) { zero = true; factors.Clear(); return; // all over } if (factor < 0) { negate = !negate; factor = -factor; } if (factor == 1) { // unit return; // nothing more to do } int power; factors.TryGetValue(factor, out power); factors[factor] = power + 1; } public void Divide(int quotient) { if (quotient == 0) throw new DivideByZeroException(); if (zero) return; if (quotient < 0) { negate = !negate; quotient = -quotient; } if (quotient == 1) { // unit return; // nothing more to do } int power; factors.TryGetValue(quotient, out power); factors[quotient] = power - 1; } public double Evaluate() { if (zero) return 0; // could also perhaps do with logarithms? double result = 1.0; foreach (KeyValuePair<int, int> pair in factors) { int factor = pair.Key, power = pair.Value; switch (power) { case 0: break; // do nothing (cancelled factor) case 1: result *= factor; break; // single mult case -1: result /= factor; break; // single div default: result *= Math.Pow(factor, power); break; // everything else } } return negate ? -result : result; } }
Rick Lones - 30 Aug 2006 13:01 GMT So you are evalulating C(m+k-1, k-1), the number of combinations of (m+k-1) things taken (k-1) at a time, correct?
Then you want:
Prod((m+1),(m+k-1)) / Prod(1, (k-1)), where:
(warning, untested code!)
long Prod(int low, int high) { long result = low; int multiplier = low;
while (++multiplier <= high) result *= multiplier;
return result; }
HTH, -rick-
> Hello, > How to calculate value for the following formula (I need C# code): [quoted text clipped - 15 lines] > Thanks, > GB GB - 30 Aug 2006 17:02 GMT Thank you , Rick. It works perfectly for me!
GB
2
> So you are evalulating C(m+k-1, k-1), the number of combinations of (m+k-1) > things taken (k-1) at a time, correct? [quoted text clipped - 38 lines] > > Thanks, > > GB
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|