Audio noob here and math challenged. I'm working with DirectSound which uses a -10000 to 0 range, converting that to a 0-100 scale.
I found this function here to obtain the millibels based on a percentage:
private int ConvertPercentageToMillibels(double value)
{
double attenuation = 1.0 / 1024.0 + value / 100.0 * 1023.0 / 1024.0;
double db = 10 * Math.Log10(attenuation) / Math.Log10(2);
return (int)(db * 100);
}
I need help getting the inverse of this function, basically to get the percentage based on millibels. Here is what I've got so far, which isn't working:
private double ConvertMillibelsToPercentage(int value)
{
double db = value / 100;
double attenuation = Math.Pow(10, db) / 10 * Math.Pow(10, 2);
double percentage = (1.0 * attenuation) - (1024.0 * 100.0 / 1023.0 * 1024.0);
return percentage;
}
Here you go!
private double ConvertMillibelsToPercentage(int value)
{
double exponent = ((value / 1000.0) + 10);
double numerator = 100.0 * (Math.Pow(2, exponent) - 1);
return numerator / 1023.0;
}
Answer will differ slightly due to obvious issues that arise from going between an int and a double.
EDIT: Per the teach how to fish request, here are the first mathematical steps toward arriving at the solution. I didn't show the whole thing because I didn't want to spoil allll the fun. All log functions should be considered Log base 10 unless otherwise noted:
millibels = db*100; // Beginning to work backward
millibels = 10*Log(attenuation)*(1/Log(2))*1000; // Substituting for db
millibels = 1000*Log(attenuation)/Log(2); // Simplifying
let millibels = m. Then:
m = 1000*Log(attenuation)/Log(2);
from here you can go two routes, you can either use properties of logs to find that:
m = 1000* Log_2(attenuation);// That is, log base 2 here
attenuation = 2^(m/1000);
OR you can ignore that particular property and realize:
attenuation = 10^(m*Log(2)/1000);
Try to work it out from one of the above options by plugging in the value that you know for attenuation:
attenuation = (1/1024)+(percentage/100)*(1023/1024);
And then solving for percentage. Good luck!
PS If you ever get stuck on things like this, I highly recommend going to the math stack exchange - there are some smart people there who love to solve math problems.
OR if you are particularly lazy and just want the answer, you can often simply type this stuff into Wolfram Alpha and it will "magically" give you the answer. Check this out
In one of my projects, I use the following smoothstep() function :
float smoothstep(float a, float b, float m, int n)
{
for(int i = 0 ; i < n ; i++)
{
m = m * m * (3 - 2 * m);
}
return a + (b - a) * m;
}
It works great, however, it has two disadvantages :
It's slow (especially for big values of n)
It doesn't work for non integer values (eg : n = 1.5)
Is there an alternative (excluding precalculating points and then interpolating) providing better performance (and same behavior), or another function giving a great approximation ?
You should be able to precompute the "m" term, since it doesn't rely on a or b, and assuming you're doing this over an entire interpolation, this should speed up your code significantly.
Alternatively, you could use the built in MathHelper.Smoothstep method, which provides a cubic interpolation, rather than the linear interpolation you get out of your version. There are also other, more advanced, interpolators in that class, also.
I have an upcoming exam the following question is very likely to come up. I'd really appreciate it if somebody could help me out. Thank you.
Using C# write a procedure to compute the following convergent series to an accuracy of 10^-10.
x^(2n-1) / (2n-1)!
I tried:
class Program
{
static void Main(string[] args)
{
double x, y, numerator, denominator, answer, e = Math.Pow(10,-10);
x = int.Parse(Console.ReadLine());
int n = 0;
do
{
numerator = Math.Pow(x, (2 * n - 1));
denominator = (2 * n - 1);
answer = (numerator / denominator);
n++;
}
while (answer < e);
}
}
My biggest problem I think, is trying to invoke the factorial function.
Notice that x^(2n+1) = x^(2n-1) * x^2 and (2n+1)! = (2n-1)! * 2n * (2n + 1). Using this formulas, you can just recalculate your numerator and denominator easily at each iteration of the loop from the previous numerator and denominator, respectively.
The rest is left for the reader.
I believe when they say "to an accuracy of 10^-10" it means the answer changes by less than that from one pass to another. Your loop looks good, but you're checking the answer itself, not the change from pass to pass. Try this change:
double lastAnswer = 0.0, delta; // couple more vars
do
{
// ... keep current code in loop, add these two lines below
delta = abs(answer - lastAnswer); // the change between passes is what's important
lastAnswer = answer; // and save last answer for next delta
}
while (delta < e); // change condition to check difference
You might also put in a "sanity check" test on n:
while ((delta < e) && (n < 10000000));
You can always increase the limit on n if your answer isn't close enough.
If your only issue is how to do a factorial, this article may help:
http://guyellisrocks.com/algorithms/factorial-function-in-c/
He makes a good point about not needing to re-calculate these values every time.
I think this is what you want:
class Program
{
static void Main(string[] args)
{
const double tol=1e-10;
double x = 1;
if(args.Length>0)
{
double.TryParse(args[0], out x);
}
int n=1;
const int n_max=100;
double y=x;
while(n<n_max && y>tol)
{
y=y*x*x/(2*n*(2*n+1));
n++;
}
Debug.WriteLine(string.Format( "x={0:R}, y={1:R}, n={2}", x, y, n));
}
}
Why? Well this is the part you can figure out on your own.
How would you refactor this code?
double p = (Convert.ToDouble(inta) / Convert.ToDouble(intb)) * 100;
double v = (p / 100) * Convert.ToDouble(intc);
return (int)v;
It seems very messy to me, I know I could squeeze it onto one line but i'd be interested to know what others would do.
Thanks
Assuming that inta, intb and intc are typed as int/Int32 then Convert.ToDouble is basically the same as a simple cast to double.
return (int)((inta / (double)intb) * intc);
Whether this is actually a worthwhile refactoring is another matter. It often makes more sense to keep intermediate calculations as separate statements to improve readability, even if you don't need those intermediate results. And, of course, having meaningful variable names makes a big difference.
Seriously, don't. What's wrong with the code as it is - ignoring possible mathematical problems and just looking at the code structure itself?
I wouldn't refactor. Squeezing it all on to one line would make it a lot harder to read. If I absolutely had to do something, I'd create new variables for the double versions of a, b, and c like this:
//set up variables
double doubleA = Convert.ToDouble(inta);
double doubleB = Convert.ToDouble(intb);
double doubleC = Convert.ToDouble(intc);
//do calculations
double p = (doubleA / doubleB) * 100
double v = (p / 100) * doubleC; //why did we divide by 100 when we multiplied by it on the line above?
return (int)v; //why are we casting back to int after all the fuss and bother with doubles?
but really I'd rather just leave it alone!
Well, for a start I'd use more meaningful names, and at a guess this is taking a ratio of integers, converting it to a percentage, applying that percentage to another original value, and returning a new value, which is the result truncated to an integer.
double percent = (Convert.ToDouble( numer ) / Convert.ToDouble( denom )) * 100;
double value = (percent / 100) * Convert.ToDouble( originalValue );
return (int)value;
One difference between using Convert and a cast is that Convert will throw an exception for out of bounds, but casting won't, and casting to int results in Int32.MinValue. So if value is too big or too little for an int, or Infinity or NaN, you will get Int32.MinValue rather than an exception at the end. The other converts can't fail, as any int can be represented as a double.
So you could write it using casts with no change in meaning, and exploit the fact that in an expression involving ints and doubles the ints are cast to doubles automatically:
double percent = ((double) numer ) / denom ) * 100;
double value = (percent / 100) * originalValue;
return (int)value;
Now, C# truncates double results on assignment to 15-16 but it's implementation defined whether intermediates are operated at higher precision. I don't think that will change the output within the range that can be cast to an int, but I don't know, and the value space is too large for an exhaustive test. So without having a specification for exactly what the function is intended to do, there is very little else you can change and be sure that you will not change the output.
If you compare these refactorings, each of which are naively mathematical equivalent, and run a range of values through them:
static int test0(int numer, int denom, int initialValue)
{
double percent = (Convert.ToDouble(numer) / Convert.ToDouble(denom)) * 100;
double value = (percent / 100) * Convert.ToDouble(initialValue);
return (int)value;
}
static int test1(int numer, int denom, int initialValue)
{
return (int)((((((double)numer) / denom) * 100 ) / 100 ) * initialValue);
}
static int test2(int numer, int denom, int initialValue)
{
return (int)((((double)numer) / denom) * initialValue);
}
static int test3(int numer, int denom, int initialValue)
{
return (int)((((double)numer) * initialValue) / denom);
}
static int test4(int numer, int denom, int initialValue)
{
if (denom == 0) return int.MinValue;
return (numer * initialValue / denom);
}
Then you get the following result of counting the number of times testN does not equal test0 and letting it run a few hours:
numer in [-10000,10000]
denom in [-10000,0) (0,10000]
initialValue in [-10000,-8709] # will get to +10000 eventually
test1 fails = 0 of 515428330128 tests, 100% accuracy.
test2 fails = 110365664 of 515428330128 tests, 99.9785875828803% accuracy.
test3 fails = 150082166 of 515428330128 tests, 99.9708820495057% accuracy.
test4 fails = 150082166 of 515428330128 tests, 99.9708820495057% accuracy.
So if you want an exactly equivalent function, then it seems that you can get to test1. Although the 100s should cancel out in test2, in reality they do effect the result in a few edge cases - the rounding of the intermediate values pushes value one side or the other of an integer. For this test, the input values were in the range -10000 to +10000, so the integer multiplication in test4 doesn't overflow, so test3 and test4 are the same. For wider input ranges, test4 will deviate more often.
Always verify your refactoring against automated tests. And don't assume that the values worked on by computers behave like the numbers in high-school mathematics.
First I will give p, v, inta, intb etc. meaningful names.
First two lines can be combined:
double pv = ((double)inta/intb)*intc;
return (int)pv;
return (int)(Convert.ToDouble(inta * intc) / Convert.ToDouble(intb));
return (int)(((double)inta / intb) * intc);
(Fixed)
A variation on #FrustratedWithFormsDes's answer:
double doubleA = (double) (inta * intc);
double doubleB = (double) intb;
return (int) (doubleA / doubleB);
There are a few interesting points that nobody else seems to have covered, so I'll add to the mix...
The first refactoring I'd do is to use good naming. Three lines of code is fine, but "p", "v", and "inta" are terrible names.
Convert.ToXXX could throw exceptions if "inta" et al are not convertible to double. In that case, you'd use double.TryParse() or a try...catch to make this code robust for any type. (Of course, as mentioned by many, if the values are just ints, then a (double) cast will suffice).
If intb has the value 0, then you will get a divide by zero exception. So you might wish to to check if intb is nonzero before using it.
So to the maths... The *100 and /100 will cancel out so are pointless. Assuming the inputs are integers (and not huge), then if you premultiply inta by intc before doing the divide, you can eliminate one (double) operation, as (int * intc) can be safely done at integer precision.
So (assuming non-huge int values, and accepting that we might throw a div-by-zero exception) the end result (without renaming for clarity) could be:
return((int) ((inta * intc) / (double) intb));
It's not a lot different from the accepted answer, but on some platforms could perform slightly better (by using an integer multiply instead of a double one).
Surely this is just
inta * intc / intb
If you don't need the value of p explicitly, you don't need to do any casting at all.
How can I calculate the value of PI using C#?
I was thinking it would be through a recursive function, if so, what would it look like and are there any math equations to back it up?
I'm not too fussy about performance, mainly how to go about it from a learning point of view.
If you want recursion:
PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...))))
This would become, after some rewriting:
PI = 2 * F(1);
with F(i):
double F (int i) {
return 1 + i / (2.0 * i + 1) * F(i + 1);
}
Isaac Newton (you may have heard of him before ;) ) came up with this trick.
Note that I left out the end condition, to keep it simple. In real life, you kind of need one.
How about using:
double pi = Math.PI;
If you want better precision than that, you will need to use an algorithmic system and the Decimal type.
If you take a close look into this really good guide:
Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4
You'll find at Page 70 this cute implementation (with minor changes from my side):
static decimal ParallelPartitionerPi(int steps)
{
decimal sum = 0.0;
decimal step = 1.0 / (decimal)steps;
object obj = new object();
Parallel.ForEach(
Partitioner.Create(0, steps),
() => 0.0,
(range, state, partial) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
decimal x = (i - 0.5) * step;
partial += 4.0 / (1.0 + x * x);
}
return partial;
},
partial => { lock (obj) sum += partial; });
return step * sum;
}
There are a couple of really, really old tricks I'm surprised to not see here.
atan(1) == PI/4, so an old chestnut when a trustworthy arc-tangent function is
present is 4*atan(1).
A very cute, fixed-ratio estimate that makes the old Western 22/7 look like dirt
is 355/113, which is good to several decimal places (at least three or four, I think).
In some cases, this is even good enough for integer arithmetic: multiply by 355 then divide by 113.
355/113 is also easy to commit to memory (for some people anyway): count one, one, three, three, five, five and remember that you're naming the digits in the denominator and numerator (if you forget which triplet goes on top, a microsecond's thought is usually going to straighten it out).
Note that 22/7 gives you: 3.14285714, which is wrong at the thousandths.
355/113 gives you 3.14159292 which isn't wrong until the ten-millionths.
Acc. to /usr/include/math.h on my box, M_PI is #define'd as:
3.14159265358979323846
which is probably good out as far as it goes.
The lesson you get from estimating PI is that there are lots of ways of doing it,
none will ever be perfect, and you have to sort them out by intended use.
355/113 is an old Chinese estimate, and I believe it pre-dates 22/7 by many years. It was taught me by a physics professor when I was an undergrad.
Good overview of different algorithms:
Computing pi;
Gauss-Legendre-Salamin.
I'm not sure about the complexity claimed for the Gauss-Legendre-Salamin algorithm in the first link (I'd say O(N log^2(N) log(log(N)))).
I do encourage you to try it, though, the convergence is really fast.
Also, I'm not really sure about why trying to convert a quite simple procedural algorithm into a recursive one?
Note that if you are interested in performance, then working at a bounded precision (typically, requiring a 'double', 'float',... output) does not really make sense, as the obvious answer in such a case is just to hardcode the value.
What is PI? The circumference of a circle divided by its diameter.
In computer graphics you can plot/draw a circle with its centre at 0,0 from a initial point x,y, the next point x',y' can be found using a simple formula:
x' = x + y / h : y' = y - x' / h
h is usually a power of 2 so that the divide can be done easily with a shift (or subtracting from the exponent on a double). h also wants to be the radius r of your circle. An easy start point would be x = r, y = 0, and then to count c the number of steps until x <= 0 to plot a quater of a circle. PI is 4 * c / r or PI is 4 * c / h
Recursion to any great depth, is usually impractical for a commercial program, but tail recursion allows an algorithm to be expressed recursively, while implemented as a loop. Recursive search algorithms can sometimes be implemented using a queue rather than the process's stack, the search has to backtrack from a deadend and take another path - these backtrack points can be put in a queue, and multiple processes can un-queue the points and try other paths.
Calculate like this:
x = 1 - 1/3 + 1/5 - 1/7 + 1/9 (... etc as far as possible.)
PI = x * 4
You have got Pi !!!
This is the simplest method I know of.
The value of PI slowly converges to the actual value of Pi (3.141592165......). If you iterate more times, the better.
Here's a nice approach (from the main Wikipedia entry on pi); it converges much faster than the simple formula discussed above, and is quite amenable to a recursive solution if your intent is to pursue recursion as a learning exercise. (Assuming that you're after the learning experience, I'm not giving any actual code.)
The underlying formula is the same as above, but this approach averages the partial sums to accelerate the convergence.
Define a two parameter function, pie(h, w), such that:
pie(0,1) = 4/1
pie(0,2) = 4/1 - 4/3
pie(0,3) = 4/1 - 4/3 + 4/5
pie(0,4) = 4/1 - 4/3 + 4/5 - 4/7
... and so on
So your first opportunity to explore recursion is to code that "horizontal" computation as the "width" parameter increases (for "height" of zero).
Then add the second dimension with this formula:
pie(h, w) = (pie(h-1,w) + pie(h-1,w+1)) / 2
which is used, of course, only for values of h greater than zero.
The nice thing about this algorithm is that you can easily mock it up with a spreadsheet to check your code as you explore the results produced by progressively larger parameters. By the time you compute pie(10,10), you'll have an approximate value for pi that's good enough for most engineering purposes.
Enumerable.Range(0, 100000000).Aggregate(0d, (tot, next) => tot += Math.Pow(-1d, next)/(2*next + 1)*4)
using System;
namespace Strings
{
class Program
{
static void Main(string[] args)
{
/* decimal pie = 1;
decimal e = -1;
*/
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start(); //added this nice stopwatch start routine
//leibniz formula in C# - code written completely by Todd Mandell 2014
/*
for (decimal f = (e += 2); f < 1000001; f++)
{
e += 2;
pie -= 1 / e;
e += 2;
pie += 1 / e;
Console.WriteLine(pie * 4);
}
decimal finalDisplayString = (pie * 4);
Console.WriteLine("pie = {0}", finalDisplayString);
Console.WriteLine("Accuracy resulting from approximately {0} steps", e/4);
*/
// Nilakantha formula - code written completely by Todd Mandell 2014
// π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) + 4/(10*11*12) - (4/(12*13*14) etc
decimal pie = 0;
decimal a = 2;
decimal b = 3;
decimal c = 4;
decimal e = 1;
for (decimal f = (e += 1); f < 100000; f++)
// Increase f where "f < 100000" to increase number of steps
{
pie += 4 / (a * b * c);
a += 2;
b += 2;
c += 2;
pie -= 4 / (a * b * c);
a += 2;
b += 2;
c += 2;
e += 1;
}
decimal finalDisplayString = (pie + 3);
Console.WriteLine("pie = {0}", finalDisplayString);
Console.WriteLine("Accuracy resulting from {0} steps", e);
stopwatch.Stop();
TimeSpan ts = stopwatch.Elapsed;
Console.WriteLine("Calc Time {0}", ts);
Console.ReadLine();
}
}
}
public static string PiNumberFinder(int digitNumber)
{
string piNumber = "3,";
int dividedBy = 11080585;
int divisor = 78256779;
int result;
for (int i = 0; i < digitNumber; i++)
{
if (dividedBy < divisor)
dividedBy *= 10;
result = dividedBy / divisor;
string resultString = result.ToString();
piNumber += resultString;
dividedBy = dividedBy - divisor * result;
}
return piNumber;
}
In any production scenario, I would compel you to look up the value, to the desired number of decimal points, and store it as a 'const' somewhere your classes can get to it.
(unless you're writing scientific 'Pi' specific software...)
Regarding...
... how to go about it from a learning point of view.
Are you trying to learning to program scientific methods? or to produce production software? I hope the community sees this as a valid question and not a nitpick.
In either case, I think writing your own Pi is a solved problem. Dmitry showed the 'Math.PI' constant already. Attack another problem in the same space! Go for generic Newton approximations or something slick.
#Thomas Kammeyer:
Note that Atan(1.0) is quite often hardcoded, so 4*Atan(1.0) is not really an 'algorithm' if you're calling a library Atan function (an quite a few already suggested indeed proceed by replacing Atan(x) by a series (or infinite product) for it, then evaluating it at x=1.
Also, there are very few cases where you'd need pi at more precision than a few tens of bits (which can be easily hardcoded!). I've worked on applications in mathematics where, to compute some (quite complicated) mathematical objects (which were polynomial with integer coefficients), I had to do arithmetic on real and complex numbers (including computing pi) with a precision of up to a few million bits... but this is not very frequent 'in real life' :)
You can look up the following example code.
I like this paper, which explains how to calculate π based on a Taylor series expansion for Arctangent.
The paper starts with the simple assumption that
Atan(1) = π/4 radians
Atan(x) can be iteratively estimated with the Taylor series
atan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9...
The paper points out why this is not particularly efficient and goes on to make a number of logical refinements in the technique. They also provide a sample program that computes π to a few thousand digits, complete with source code, including the infinite-precision math routines required.
The following link shows how to calculate the pi constant based on its definition as an integral, that can be written as a limit of a summation, it's very interesting:
https://sites.google.com/site/rcorcs/posts/calculatingthepiconstant
The file "Pi as an integral" explains this method used in this post.
First, note that C# can use the Math.PI field of the .NET framework:
https://msdn.microsoft.com/en-us/library/system.math.pi(v=vs.110).aspx
The nice feature here is that it's a full-precision double that you can either use, or compare with computed results. The tabs at that URL have similar constants for C++, F# and Visual Basic.
To calculate more places, you can write your own extended-precision code. One that is quick to code and reasonably fast and easy to program is:
Pi = 4 * [4 * arctan (1/5) - arctan (1/239)]
This formula and many others, including some that converge at amazingly fast rates, such as 50 digits per term, are at Wolfram:
Wolfram Pi Formulas
PI (π) can be calculated by using infinite series. Here are two examples:
Gregory-Leibniz Series:
π/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
C# method :
public static decimal GregoryLeibnizGetPI(int n)
{
decimal sum = 0;
decimal temp = 0;
for (int i = 0; i < n; i++)
{
temp = 4m / (1 + 2 * i);
sum += i % 2 == 0 ? temp : -temp;
}
return sum;
}
Nilakantha Series:
π = 3 + 4 / (2x3x4) - 4 / (4x5x6) + 4 / (6x7x8) - 4 / (8x9x10) + ...
C# method:
public static decimal NilakanthaGetPI(int n)
{
decimal sum = 0;
decimal temp = 0;
decimal a = 2, b = 3, c = 4;
for (int i = 0; i < n; i++)
{
temp = 4 / (a * b * c);
sum += i % 2 == 0 ? temp : -temp;
a += 2; b += 2; c += 2;
}
return 3 + sum;
}
The input parameter n for both functions represents the number of iteration.
The Nilakantha Series in comparison with Gregory-Leibniz Series converges more quickly. The methods can be tested with the following code:
static void Main(string[] args)
{
const decimal pi = 3.1415926535897932384626433832m;
Console.WriteLine($"PI = {pi}");
//Nilakantha Series
int iterationsN = 100;
decimal nilakanthaPI = NilakanthaGetPI(iterationsN);
decimal CalcErrorNilakantha = pi - nilakanthaPI;
Console.WriteLine($"\nNilakantha Series -> PI = {nilakanthaPI}");
Console.WriteLine($"Calculation error = {CalcErrorNilakantha}");
int numDecNilakantha = pi.ToString().Zip(nilakanthaPI.ToString(), (x, y) => x == y).TakeWhile(x => x).Count() - 2;
Console.WriteLine($"Number of correct decimals = {numDecNilakantha}");
Console.WriteLine($"Number of iterations = {iterationsN}");
//Gregory-Leibniz Series
int iterationsGL = 1000000;
decimal GregoryLeibnizPI = GregoryLeibnizGetPI(iterationsGL);
decimal CalcErrorGregoryLeibniz = pi - GregoryLeibnizPI;
Console.WriteLine($"\nGregory-Leibniz Series -> PI = {GregoryLeibnizPI}");
Console.WriteLine($"Calculation error = {CalcErrorGregoryLeibniz}");
int numDecGregoryLeibniz = pi.ToString().Zip(GregoryLeibnizPI.ToString(), (x, y) => x == y).TakeWhile(x => x).Count() - 2;
Console.WriteLine($"Number of correct decimals = {numDecGregoryLeibniz}");
Console.WriteLine($"Number of iterations = {iterationsGL}");
Console.ReadKey();
}
The following output shows that Nilakantha Series returns six correct decimals of PI with one hundred iterations whereas Gregory-Leibniz Series returns five correct decimals of PI with one million iterations:
My code can be tested >> here
Here is a nice way:
Calculate a series of 1/x^2 for x from 1 to what ever you want- the bigger number- the better pie result. Multiply the result by 6 and to sqrt().
Here is the code in c# (main only):
static void Main(string[] args)
{
double counter = 0;
for (double i = 1; i < 1000000; i++)
{
counter = counter + (1 / (Math.Pow(i, 2)));
}
counter = counter * 6;
counter = Math.Sqrt(counter);
Console.WriteLine(counter);
}
public double PI = 22.0 / 7.0;