I have a problem with setting the maximum and minimum values for the y-axis of my mschart.
When setting the max or min to a value, say 10.025, the value the chart sets as max is 10.024999618530273.
mainChart.ChartAreas[selectedChartArea].AxisY.Maximum = GetRoundYAxisMax(newYMax, newYRange);
mainChart.ChartAreas[selectedChartArea].AxisY.Minimum = GetRoundYAxisMin(newYMin, newYRange);
The GetRoundYAxisMax method just returns a "round" value. Code below.
private float GetRoundYAxisMax(double calculatedMax, double yAxisRange)
{
double rangeFactor = 0;
if (yAxisRange > 10)
rangeFactor = 1;
else if (yAxisRange > 1)
rangeFactor = 4;
else if (yAxisRange > 0.1)
rangeFactor = 40;
else if (yAxisRange > 0.01)
rangeFactor = 400;
else if (yAxisRange > 0.001)
rangeFactor = 4000;
else if (yAxisRange > 0.0001)
rangeFactor = 40000;
else
rangeFactor = 400000;
float returnValue = (float)(Math.Round(calculatedMax * rangeFactor, MidpointRounding.ToEven) / rangeFactor);
return returnValue;
}
The rounding code evaluates properly and returns a correctly rounded value, but when setting this value to the max or min value on the y-axis it sets a value very close to it, but not rounded.
Any ideas why this is happening?
You can set the axis label style to round the un-rounded values:
mainChart.ChartAreas[selectedChartArea].AxisY.LabelStyle.Format = "#.###";
Just answering why 10.024999618530273 rather than 10.025.
Nothing on a computer is infinite in precision. You have ( IIRC ) 80 bits to represent your number. Part is exponent part is mantissa. What is happening is that 10.025 is not a number that has perfect representation in that number of bits. You dont get the whole number line, you get integral marks along it. ( take a random 80 bit double. That is a point on the number line. Now, add the smallest increment to that 80 bit double that is possible. Another point on the line. Now, in the "real" ( pun intended ) world, there are an infinite number of real points. Any point on the line you try to represent on a real world number line will be represented as one of the two points that bound that point in the 80 bit world ).
Related
Hey i'm comparing 2 Vector.y's but it isnt working!
Here the code:
print(last.y + " == " + controller.transform.position.y);
if (last.y == controller.transform.position.y)
The print: 0,7999999 == 0,7999999
You are comparing floating point numbers. To get those exactly equal is hard. Unity only shows a limited amount of decimals in the editor. Try rounding the numbers.
https://docs.unity3d.com/ScriptReference/Mathf.Round.html
I.e.:
float randomNumber = 2.543686;
randomNumber = Mathf.Round(randomNumber * 100.0) / 100.0;
will return 2.54
Depending on how precise you want you could also do:
// If absolute difference between last y and controller pos y is less than 0.0001
if (Mathf.abs(last.y - controller.transformer.position.y) < 0.0001f) {
// do something
}
I am using Dundas Charts in Visual Studio using C#.
My charts are displaying percentage values, if I do not use a maximum y axis value the chart will automatically scale the axis - however, sometimes it will display values over 100% (even though none of the values actually exceed 100%).
How can I allow the axis to change in size depending on chart values, but never allow it to exceed 100%?
For anyonewho is interested, I decided to programmatically set the maximum value for the Y Axis for each chart.
The following code is used to get the max value from the given array and return 100 or the max value rounded up to the next multiple of 10:
int GetYAxisMaxValue(decimal[] yValues)
{
var max = yValues.Max();
var output = 0m;
if (yValues.Max() % 10 == 0) output = max;
else output = max + (10 - max % 10);
if (output > 100) return 100;
else return Convert.ToInt32(output);
}
This is then used to create the chart, setting:
chart.ChartAreas["Default"].AxisY.Maximum = GetYAxisMaxValue(...);
Hope this helps.
I have a charts populated in asp.net C#. I have multiple charts and each can range from 0 - 125.
which look like this if I do not set the maximum which one of it, the chart maximum will go to 140 if my series range max is 125.:
Thus I would like to set the maximum of Y axis to 125 however not staticly setting it for all charts. which mean I would like to make it dynamic still like the second chart image with the maximum set as 125.
Please advice thanks.
// Maximum value in Series, you may have to change YValues[0] to the appropriate
// index for your type of chart (so that it measures the top of your markers)
double maxValue = chart.Series[0].Points.Max(x => x.YValues[0])
// yAxisMax calculated as max value in series + 10 then rounded up to nearest 10
// but capped at 125 below. You could change this to perhaps
// maxValue * 1.1 to always get a 10 % extra above, anything goes
double yAxisMax = Math.Ceiling((maxValue + 10) / 10) * 10;
if (yAxisMax > 125)
yAxisMax = 125;
chart.ChartAreas[0].AxisY.Minimum = 0;
chart.ChartAreas[0].AxisY.Maximum = yAxisMax;
chart.ChartAreas[0].AxisY.Interval = 5;
I don't know how to describe it very well (so I can't look it up) but I need help. Lets say I have 100 out of 0 to 200, how do I ratio the number to 0 to 100 so it would be like 50? Simply ratio-ing the number to a smaller or bigger size?
Calculate the ratio between the original maximum and the new maximum:
double k = (double)newMax / (double)oldMax
In your example you would end up with the value 0.5.
Then just multiply the value with the ratio:
double newValue = value * k;
If you want an integer value, round it and convert to integer:
int newValue = (int)Math.Round(value * k);
In general, when the minimum is not necessarily 0 on either the 'old' and 'new scales', the solution is the following:
ratio = ( oldValue - oldMin ) / ( oldMax - oldMin )
newValue = newMin + ( newMax - newMin ) * ratio
double myRatio, maxValue, newValue;
//value retrieval logics.
double result = (myRatio / maxValue) * newMaxValue;
u gotta fill the doubles on the first line in.
this is the shortest code I'd say.
((Max - value) / Max) * (newMax)
Currently I am writing my thesis and I was confronted with a behavior of .Net C# that I had never seen before. I am talking about an error in a calculation.
I implemented this formula:
1/2 * (Theta i-1 + Theta i) + Sum(Alph k, k=1, i-1)
This formula is applied to 4 objects. Theta is in all objects declared as float with the value 1,5708. Alpha is initialized with 0 and will be increased by each iteration.
First implmentation
float alpha = 0;
float value = 0;
for (int sphereCount = 1; sphereCount < this.spheres.Count; sphereCount++)
{
value = (1/2) * (this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta);
alpha += value;
}
With this version value is always 0.0!
So I changed it to:
Working implementaion
float alpha = 0;
float value = 0;
for (int sphereCount = 1; sphereCount < this.spheres.Count; sphereCount++)
{
value =(this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) * 1/2;
alpha += value;
}
By removing the brackets around the 1/2 and placing it at the end of the calculation it worked.
WHY IS THAT SO???
It seems when you place 1/2 in brackets not depending on the position of 1/2 the result is 0.0. But also when i place (1/2) at the end it results in 0.0.
Does anyone here have an idea why?
This
(1 / 2)
evaluates to 0 because it's integer division. If you say
(1 / 2f)
or
(1 / (float) 2)
you'll be fine because it forces float divsion. Or, even better, just write 0.5.
If you write 1/2 the result is calculated using integer division that gives an integer result. You can force a floating point division by changing one of the numbers to a floating point number, as in 1/2f.
Or you could just write 0.5 which IMHO is more readable than 1/2.
Why multiply by 1? Rather than this:
value =(this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) * 1/2;
why not write this:
value =(this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) / 2;
You should write 1.0/2 or 0.5 instead 1/2.
1/2 is an integer division which results in an integer 0.
Because 1/2 is treated as integer arithmetic and as such is rounded to 0.
Removing the parenthesis changes the order of operations, and now you are dividing your whole (floating point) formula by two and arriving at a floating point answer.
That's because 1 and 2 are integer values, not floating point values.
When you divide the integer value 1 by the integer value 2, the result is the integer value 0, not the floating point value 0.5.
When you remove the parentheses and change the order of the multiplication, the other part of the expression will first be multiplied by 1, which will implicitly convert the integer value 1 into a floating point value. Then the result is divided by 2, which will also be implicitly converted into a floating point value.
So what you end up doing is:
value = ( (this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) * (float)1 ) / (float)2;