C#: Equation not working? - c#

I looked pretty much all over google for this but it didn't have any questions that really seemed like they were directed to the problem I was having so I posted here to see if you guys knew what was up with the below code example I have posted on this forum so yeah.
Hello. I have a minimum number (3200) and a maximum number (4000) and then a 3rd number (3663), I am trying to get the progression the 3rd number is between the minimum number and the maximum number.
I'll explain it in better terms, I have levels which have xp counts they start at. I am trying to get the progression to the next level.
Raw [C#]: (3663 - 3200) / (4000 - 3200) * 100
Code:
int progression = (newXp - Convert.ToInt32(currentGrade["grade_xp_needed"])) / (Convert.ToInt32(newGrade["grade_xp_needed"]) - Convert.ToInt32(currentGrade["grade_xp_needed"])) * 100;
Why is it returning 0% but I still have 300 or something XP to go? I've worked it out in PHP and it returns 57%
PHP Code:
$progression = round(($currentXp - $currentGrade->grade_xp_needed) / ($nextGrade->grade_xp_needed - $currentGrade->grade_xp_needed) * 100, 1);

You need to convert the values to decimal to get the correct division results. Then you can convert back the result of the whole equation into integer.
int progression = (int)((newXp - Convert.ToDecimal(currentGrade["grade_xp_needed"]))
/ (Convert.ToDecimal(newGrade["grade_xp_needed"])
- Convert.ToDecimal(currentGrade["grade_xp_needed"])) * 100);
in C#, int divided by an int results in a int.

You are getting a wrong result, since you are performing an integer calculation.
Make any one of numerator or denominator as a float and it will work.
int progression = (int) ((1.0*(newXp - Convert.ToInt32(currentGrade["grade_xp_needed"]))) / (Convert.ToInt32(newGrade["grade_xp_needed"]) - Convert.ToInt32(currentGrade["grade_xp_needed"])) * 100);
Hope this helps.

You have to use double instead of integer.
See this link for sample code and output.
public static void Main()
{
double low = 3200;
double high = 4000;
double xp = 3663;
double progression = (xp - low) / (high - low) * 100;
Console.WriteLine(progression + "%");
}

Related

Get the inverse of a function, millibels to percentage & percentage to millibels

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

Time to Temperature Calculation

This might not be the correct place for this, so apologies in advance if it isn't.
My situation - I need to come up with a simple formula/method of giving it an hour E.g. 13, 15, 01 etc, and based on that number, the method will return the 'approx' temperature for that particular time.
This is very approximate and it will not use weather data or anything like that, it will just take the hour of the day and return a value between say -6 deg C > 35 deg C. (very extreme weather, but you get the idea.)
This is the sort of examples I would like to know how to do:
Just as a note, I COULD use an ugly array of 24 items, each referencing the temp for that hour, but this needs to be float based - e.g. 19.76 should return 9.25 deg...
Another note: I don't want a complete solution - I'm a confident programmer in various languages, but the maths have really stumped me on this. I've tried various methods on paper using TimeToPeak (the peak hour being 1pm or around there) but to no avail. Any help would be appreciated at this point.
EDIT
Following your comment, here is a function that provides a sinusoidal distribution with various useful optional parameters.
private static double SinDistribution(
double value,
double lowToHighMeanPoint = 0.0,
double length = 10.0,
double low = -1.0,
double high = 1.0)
{
var amplitude = (high - low) / 2;
var mean = low + amplitude;
return mean + (amplitude * Math.Sin(
(((value - lowToHighMeanPoint) % length) / length) * 2 * Math.PI));
}
You could use it like this, to get the results you desired.
for (double i = 0.0; i < 24.0; i++)
{
Console.WriteLine("{0}: {1}", i, SinDistribution(i, 6.5, 24.0, -6.0, 35.0));
}
This obviously discounts environmental factors and assumes the day is an equinox but I think it answers the question.
So,
double EstimatedTemperature(double hour, double[] distribution)
{
var low = Math.Floor(hour);
var lowIndex = (int)low;
var highIndex = (int)Math.Ceiling(hour);
if (highIndex > distribution.Count - 1)
{
highIndex = 0;
}
if (lowIndex < 0)
{
lowIndex = distribution.Count - 1;
}
var lowValue = distribution.ElementAt(lowIndex);
var highValue = distribution.ElementAt(highIndex);
return lowValue + ((hour - low) * (highValue - lowValue));
}
assuming a rather simplistic linear transition between each point in the distibution. You'll get erroneous results if the hour is mapped to elements that are not present in the distribution.
For arbitrary data points, I would go with one of the other linear interpolation solutions that have been provided.
However, this particular set of data is generated by a triangle wave:
temp = 45*Math.Abs(2*((t-1)/24-Math.Floor((t-1)/24+.5)))-10;
The data in your table is linear up and down from a peak at hour 13 and a minimum at hour 1. If that is the type of model that you want then this is really easy to put into a formulaic solution. You would just simply perform linear interpolation between the two extremes of the temperature based upon the hour value. You would have two data points:
(xmin, ymin) as (hour-min, temp-min)
(xmax, ymax) as (hour-max, temp-max)
You would have two equations of the form:
The two equations would use the (x0, y0) and (x1, y1) values as the above two data points but apply them the opposite assignment (ie peak would be (x0, y0) on one and (x1, y1) in the other equation.
You would then select which equation to use based upon the hour value, insert the X value as the hour and compute as Y for the temperature value.
You will want to offset the X values used in the equations so that you take care of the offset between when Hour 0 and where the minimum temperature peak happens.
Here is an example of how you could do this using a simple set of values in the function, if you wish, add these as parameters;
public double GetTemp(double hour)
{
int min = 1;
int max = min + 12;
double lowest = -10;
double highest = 35;
double change = 3.75;
return (hour > max) ? ((max - hour) * change) + highest : (hour < min) ? ((min - hour)*change) + lowest : ((hour - max) * change) + highest;
}
I have tested this according to your example and it is working with 19.75 = 9.6875.
There is no check to see whether the value entered is within 0-24, but that you can probably manage yourself :)
You can use simple 2 point linear approximation. Try somthing like this:
function double hourTemp(double hour)
{
idx1 = round(hour);
idx2 = idx1 + 1;
return (data[idx2] - data[idx1]) * (hour - idx1) + data[idx1];
}
Or use 3,5 or more points to get polynom cofficients with Ordinary Least Squares method.
Your sample data similar to the sin function so you can make sin function approximation.

Round a number to the next HIGHEST 10

I have a need to create a graph, where the scale of the Y-axis changes depending on the data input into the system. Conceivably this scale could be anywhere from 0-10, 0-100, or even have bottom limit of thousands and an upper limit of millions.
To properly determinethe scale of this axis, I need to work out the ratio of Points to Pixels (based on graph height/range).
Now a graphs' axis never start at the lowest value and go to the highest, usual practice is to go to the next nearest 2, 5 or 10 (above for upper limit, and below for lower) depending on the range of values.
So what I'd like to know is how to take the max value from the data set, and round it up to the nearest 10.
for clarification, the input values will always be integers.
what i have now is this
if ((rangeMax < 10) && (rangeMax > 5))
rangeMax = 10;
else if (rangeMax < 5)
rangeMax = 5;
Which is only useful for values less than 10, and doesn't allow the flexibility required to be truly dynamic. Ultimately this graph will be auto-generated during a page load event, with no user input.
I've read around a bit, and people talk about things like the modulus operator (%), but I can't find any reliable information about it's use, and talk of Math.Ceiling and Math.Round, but these go to the next nearest whole number, which isn't quite there, and don't seem to help much at all when dealing with integers anyway.
Any suggestions, pointers or help greatly appreciated.
i did find a similar question asked here How can i get the next highest multiple of 5 or 10 but i don't know java, so i can't understand any of what was said.
Cheers
if(rangeMax % 10 !=0)
rangeMax = (rangeMax - rangeMax % 10) + 10;
You could also use Math.Round() with MidpointRounding.AwayFromZero using a decimal number (otherwise integer division will truncate fractions):
decimal number = 55M;
decimal nextHighest = Math.Round(number/ 10, MidpointRounding.AwayFromZero) * 10;
If you want to go up to the next 10, you can use Math.Ceiling as follows:
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / 10) * 10);
If you need to generalize to go to the next n (for example 5 here) you can do:
int n = 5;
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / n) * n);
Something which might help is to divide the number by 10. This should round it to the nearest integer. Then multiply it by 10 again to get the number rounded to the nearest 10
I use THIS:
public static double RoundTo10(double number)
{
if (number > 0)
{
return Math.Ceiling(number / 10) * 10;
}
else
{
return Math.Floor(number / 10) * 10;
}
}
you can try this....
decimal val = 95;
//decimal val =Convert.ToDecimal( textBox1.Text);
decimal tmp = 0;
tmp = (val % 10);
//MessageBox.Show(tmp.ToString()+ "Final val:"+(val-tmp).ToString());
decimal finval = val - tmp;

Detect a specific frequency/tone from raw wave-data

I am reading a raw wave stream coming from the microphone. (This part works as I can send it to the speaker and get a nice echo.)
For simplicity lets say I want to detect a DTMF-tone in the wave data. In reality I want to detect any frequency, not just those in DTMF. But I always know which frequency I am looking for.
I have tried running it through FFT, but it doesn't seem very efficient if I want high accuracy in the detection (say it is there for only 20 ms). I can detect it down to an accuracy of around 200 ms.
What are my options with regards to algorithms?
Are there any .Net libs for it?
You may want to look at the Goertzel algorithm if you're trying to detect specific frequencies such as DTMF input. There is a C# DTMF generator/detector library on Sourceforge based on this algorithm.
Very nice implementation of Goertzel is there. C# modification:
private double GoertzelFilter(float[] samples, double freq, int start, int end)
{
double sPrev = 0.0;
double sPrev2 = 0.0;
int i;
double normalizedfreq = freq / SIGNAL_SAMPLE_RATE;
double coeff = 2 * Math.Cos(2 * Math.PI * normalizedfreq);
for (i = start; i < end; i++)
{
double s = samples[i] + coeff * sPrev - sPrev2;
sPrev2 = sPrev;
sPrev = s;
}
double power = sPrev2 * sPrev2 + sPrev * sPrev - coeff * sPrev * sPrev2;
return power;
}
Works great for me.
Let's say that typical DTMF frequency is 200Hz - 1000Hz. Then you'd have to detect a signal based on between 4 and 20 cycles. FFT will not get you anywhere I guess, since you'll detect only multiples of 50Hz frequencies: this is a built in feature of FFT, increasing the number of samples will not solve your problem. You'll have to do something more clever.
Your best shot is to linear least-square fit your data to
h(t) = A cos (omega t) + B sin (omega t)
for a given omega (one of the DTMF frequencies). See this for details (in particular how to set a statistical significance level) and links to the litterature.
I found this as a simple implementation of Goertzel. Haven't gotten it to work yet (looking for wrong frequency?), but I thought I'd share it anywas. It is copied from this site.
public static double CalculateGoertzel(byte[] sample, double frequency, int samplerate)
{
double Skn, Skn1, Skn2;
Skn = Skn1 = Skn2 = 0;
for (int i = 0; i < sample.Length; i++)
{
Skn2 = Skn1;
Skn1 = Skn;
Skn = 2 * Math.Cos(2 * Math.PI * frequency / samplerate) * Skn1 - Skn2 + sample[i];
}
double WNk = Math.Exp(-2 * Math.PI * frequency / samplerate);
return 20 * Math.Log10(Math.Abs((Skn - WNk * Skn1)));
}
As far as any .NET libraries that do this try TAPIEx ToneDecoder.Net Component. I use it for detecting DTMF, but it can do custom tones as well.
I know this question is old, but maybe it will save someone else several days of searching and trying out code samples and libraries that just don't work.
Spectral Analysis.
All application where you extract frequencies from signals goes under field spectral analysis.

Evaluate if two doubles are equal based on a given precision, not within a certain fixed tolerance

I'm running NUnit tests to evaluate some known test data and calculated results. The numbers are floating point doubles so I don't expect them to be exactly equal, but I'm not sure how to treat them as equal for a given precision.
In NUnit we can compare with a fixed tolerance:
double expected = 0.389842845321551d;
double actual = 0.38984284532155145d; // really comes from a data import
Expect(actual, EqualTo(expected).Within(0.000000000000001));
and that works fine for numbers below zero, but as the numbers grow the tolerance really needs to be changed so we always care about the same number of digits of precision.
Specifically, this test fails:
double expected = 1.95346834136148d;
double actual = 1.9534683413614817d; // really comes from a data import
Expect(actual, EqualTo(expected).Within(0.000000000000001));
and of course larger numbers fail with tolerance..
double expected = 1632.4587642911599d;
double actual = 1632.4587642911633d; // really comes from a data import
Expect(actual, EqualTo(expected).Within(0.000000000000001));
What's the correct way to evaluate two floating point numbers are equal with a given precision? Is there a built-in way to do this in NUnit?
From msdn:
By default, a Double value contains 15 decimal digits of precision, although a maximum of 17 digits is maintained internally.
Let's assume 15, then.
So, we could say that we want the tolerance to be to the same degree.
How many precise figures do we have after the decimal point? We need to know the distance of the most significant digit from the decimal point, right? The magnitude. We can get this with a Log10.
Then we need to divide 1 by 10 ^ precision to get a value around the precision we want.
Now, you'll need to do more test cases than I have, but this seems to work:
double expected = 1632.4587642911599d;
double actual = 1632.4587642911633d; // really comes from a data import
// Log10(100) = 2, so to get the manitude we add 1.
int magnitude = 1 + (expected == 0.0 ? -1 : Convert.ToInt32(Math.Floor(Math.Log10(expected))));
int precision = 15 - magnitude ;
double tolerance = 1.0 / Math.Pow(10, precision);
Assert.That(actual, Is.EqualTo(expected).Within(tolerance));
It's late - there could be a gotcha in here. I tested it against your three sets of test data and each passed. Changing pricision to be 16 - magnitude caused the test to fail. Setting it to 14 - magnitude obviously caused it to pass as the tolerance was greater.
This is what I came up with for The Floating-Point Guide (Java code, but should translate easily, and comes with a test suite, which you really really need):
public static boolean nearlyEqual(float a, float b, float epsilon)
{
final float absA = Math.abs(a);
final float absB = Math.abs(b);
final float diff = Math.abs(a - b);
if (a * b == 0) { // a or b or both are zero
// relative error is not meaningful here
return diff < (epsilon * epsilon);
} else { // use relative error
return diff / (absA + absB) < epsilon;
}
}
The really tricky question is what to do when one of the numbers to compare is zero. The best answer may be that such a comparison should always consider the domain meaning of the numbers being compared rather than trying to be universal.
How about converting the items each to string and comparing the strings?
string test1 = String.Format("{0:0.0##}", expected);
string test2 = String.Format("{0:0.0##}", actual);
Assert.AreEqual(test1, test2);
Assert.That(x, Is.EqualTo(y).Within(10).Percent);
is a decent option (changes it to a relative comparison, where x is required to be within 10% of y). You may want to add extra handling for 0, as otherwise you'll get an exact comparison in that case.
Update:
Another good option is
Assert.That(x, Is.EqualTo(y).Within(1).Ulps);
where Ulps means units in the last place. See https://docs.nunit.org/articles/nunit/writing-tests/constraints/EqualConstraint.html#comparing-floating-point-values.
I don't know if there's a built-in way to do it with nunit, but I would suggest multiplying each float by the 10x the precision you're seeking, storing the results as longs, and comparing the two longs to each other.
For example:
double expected = 1632.4587642911599d;
double actual = 1632.4587642911633d;
//for a precision of 4
long lActual = (long) 10000 * actual;
long lExpected = (long) 10000 * expected;
if(lActual == lExpected) { // Do comparison
// Perform desired actions
}
This is a quick idea, but how about shifting them down till they are below zero? Should be something like num/(10^ceil(log10(num))) . . . not to sure about how well it would work, but its an idea.
1632.4587642911599 / (10^ceil(log10(1632.4587642911599))) = 0.16324587642911599
How about:
const double significantFigures = 10;
Assert.AreEqual(Actual / Expected, 1.0, 1.0 / Math.Pow(10, significantFigures));
The difference between the two values should be less than either value divided by the precision.
Assert.Less(Math.Abs(firstValue - secondValue), firstValue / Math.Pow(10, precision));
open FsUnit
actual |> should (equalWithin errorMargin) expected

Categories