I'm trying to translate this function from excel to C#:
=10^(0.1*(-44.1224+3.32*(-97.060520104064452*LOG(0.89*(200/160)))))
excel gives me: 1.2467E-06
var value = Math.Pow(10, 0.1 * (-44.1224 + 3.32 * (-97.060520104064452 * Math.Log10(0.89 * (200 / 160)))));
C# gives me c#value = 0.0016543260792358536
Anybody has any ideas why I don't get the same value in excel and c#?
Because C# is rounding for you.
Change this:
200 / 160
To
200.0 / 160.0
Output locally:
1.24676291550131E-06
It's because 200/160 is being cast to an integer, which truncates your result. To fix the issue, you can do as Rob suggested and write the numerator or demoniator as a floating point number. See the / operator reference.
Related
I've got this Excel equation and I'm struggling to convert it into c#.
The "to the power of" and "log" parts are tripping me up.
The excel equation is as follows:
LOG((10^(PreSkillRating/400)/((-ChangeInRating/KFactor)+1)-10^(PreSkillRating/400)))*400/LOG(10)
So far I have this:
Math.Log((Math.Pow(PreSkillRating / 400, 10)) / (((ChangeInRating * -1) / KFactor) + 1) - Math.Pow((PreSkillRating / 400), 10)) * 400 / Math.Log(10)
I'm also aware that I will have to check for 0 when dividing to stop the Attempted to divide by zero error.
For example when I use the following values for each of the variables I get 1879.588002 as the answer in excel but infinity in c#.
PreSkillRating = 1600
ChangeInRating = 50
KFactor = 60
What am I doing wrong?
Based on earler comments and my first answer, let's summarize:
typecast for double division
wrong order of arguments for Pow
wrong method Math.Log(x). You can use Math.Log(x,10) or Math.Log10(x)
Try following implementation:
Math.Log10((Math.Pow(10, (double)PreSkillRating / 400)) / (((ChangeInRating * -1.0) / KFactor) + 1) - Math.Pow(10, (double)PreSkillRating / 400)) * 400 / Math.Log10(10)
Are your variables int values?
Then you have to add a typecast. See Division in C# to get exact value
Otherwise, divisions are performed as integer divisions, which causes rounding operation for each step separately.
This question already has answers here:
Why is floating point arithmetic in C# imprecise?
(3 answers)
Closed 7 years ago.
I just did a test with LINQPad:
Could you explain me why/how the ceiling method is reacting like this? Notice the 123.12 in the middle.
Math.Ceiling(123.121 * 100) / 100 'display 123.13
Math.Ceiling(123.1200000000001 * 100) / 100 'display 123.13
Math.Ceiling(123.12000000000001 * 100) / 100 'display 123.12
Math.Ceiling(123.12000000000002 * 100) / 100 'display 123.13
I did the test in VB.NET but it should be the same in C#.
This is floating point rounding. C# parses 123.12000000000001 and 123.12 as having the same value. 123.12000000000002 is parsed as the next available double.
var bytes = BitConverter.ToString(BitConverter.GetBytes(123.12));
// outputs 48-E1-7A-14-AE-C7-5E-40
var bytes1 = BitConverter.ToString(BitConverter.GetBytes(123.12000000000001));
// outputs 48-E1-7A-14-AE-C7-5E-40
var bytes2 = BitConverter.ToString(BitConverter.GetBytes(123.12000000000002));
// outputs 49-E1-7A-14-AE-C7-5E-40
Ceiling returns the number passed to it if they are whole numbers, or else the next highest whole number. So 5.0 stays 5.0 but 5.00001 becomes 6.0.
So, of the examples, the following are obvious:
Math.Ceiling(123.121 * 100) / 100 // Obtain 12312.1, next highest is 12313.0, then divide by 100 is 123.13
Math.Ceiling(123.1200000000001 * 100) / 100 // Likewise
Math.Ceiling(123.12000000000002 * 100) / 100 // Likewise
The more confusing one is:
Math.Ceiling(123.12000000000001 * 100) / 100 //display 123.12
However, let's take a look at:
123.12000000000001 * 100 - 12312.0 // returns 0
Compared to:
123.1200000000001 * 100 - 12312.0 // returns 1.09139364212751E-11
123.12000000000002 * 100 - 12312.0 // returns 1.81898940354586E-12
The latter two multiplications have results that are slightly higher than 12312.0, so while (123.12000000000002 * 100).ToString() returns "12312" the actual number produced by 123.12000000000002 * 100 is mathematically 12312.000000000002 the nearest possible double for 123.12000000000002 is is 123.1200000000000181898940354586 so that is what is worked on.
If you are used to only doing decimal arithmetic it may seem strange that 123.12000000000002 is "rounded" to 123.1200000000000181898940354586, but remember that these numbers are stored in terms of binary values, and rounding depends on the base you are working in.
So while the string representation doesn't indicate it, it is indeed slightly higher than 12312 and so its ceiling is 12313.
Meanwhile with 123.12000000000001 * 100, that is mathematically 12312.000000000001 but the nearest possible double to 123.12000000000001 is that it can fit into is 123.12. So that is what is used for the multiplication, and when the result passed to the subsequent call to Ceiling() its result is 12312.
This is due to floating point rounding rather than Math.Ceiling per se which is because floating point values cannot represent all values with 100% accuracy.
Your example is a little contrived anyway because if you try to type 123.12000000000001 in visual studio is changes it to 123.12 because it knows that the value cannot be represented as a double.
Read up on this here: What Every Computer Scientist Should Know About Floating-Point Arithmetic (btw this is not specific to .NET)
To fix your issue you can use a decimal value instead of a double. Math.Ceiling has an overload which accepts a decimal (all of these display 123.13):
Debug.WriteLine(Math.Ceiling(123.121D * 100) / 100)
Debug.WriteLine(Math.Ceiling(123.1200000000001D * 100) / 100)
Debug.WriteLine(Math.Ceiling(123.12000000000001D * 100) / 100)
Debug.WriteLine(Math.Ceiling(123.12000000000002D * 100) / 100)
Whether this fix is appropriate of course depends on what level of accuracy you require.
The Ceiling method returns the next higher integer equivalent.
so Ceiling(123.01) = 124
& Ceiling(123.0) = 123
I am baffled by this one.
So I have a console application doing a lot of calculations (trust me, thousands of them ). In one method, I have some parameters that need calculating, in different situations. For one of them, the mathematical expression is basically the same, only one difference in a term. Here is the code snippet along with all the lines between the 2 formulas in question, the Nq1 and Nq2 ones ( first formula of the code and last one to be more easy ):
//drained conditions
Nq1 = Math.Round((Math.Pow(Math.E, Math.PI * Math.Tan(studiu.Fi * Constants.ConversionToDeg)) * Math.Pow((Math.Tan(45 + studiu.Fi / 2.00) * Constants.ConversionToDeg), 2)), 2);
//Combination 2
studiu.Fi = FiAfectat;
//drained conditions
Nq2 = Math.Round((Math.Pow(Math.E, Math.PI * Math.Tan(studiu.Fi * Constants.ConversionToDeg)) * Math.Pow((Math.Tan(45 + studiu.Fi / 2.00) * Constants.ConversionToDeg), 2)), 2);
The first formula returns 18.04 but the second one returns 0.01. How is this possible ? Only the studiu.Fi term differs, but not by that much ( 32 in the first case and 27 in the second ).
How can Nq1 be 18 and Nq2 be 0.01 ? Am I missing something here ?
Tan(x) is a periodic function that will change drastically for a small change in x. Since the two formulas only differ by a term inside the Tan function, this is likely your problem.
Also, it is likely that you should be using radians instead of degrees. If this is the case you should use a command that converts real numbers to radians instead of one that converts to degrees.
why rounds C# this calculation up?
500 -> 501
MessageBox.Show(Math.Ceiling(1 / (4 * 1 - 4 * 0.9) * 200).ToString());
Returns.
---------------------------
---------------------------
501
---------------------------
OK
---------------------------
I dont know why.
Excel doesnt do this, too.
I need the ceiling function for the fomula which returns 500 instead 501.
I could use this instead. But i would know if there is another solution and why C# do this.
MessageBox.Show(Math.Ceiling(Math.Floor((1 / (4 * 1 - 4 * 0.9) * 200) * 100) / 100).ToString());
The problem is that 500 is actually not 500 but rather 500.0000000001 (or something similar) due to using floating point operations.
To solve this issue, use decimal instead of double.
MessageBox.Show(Math.Ceiling(1.0M / (4.0M * 1.0M - 4.0M * 0.9M) * 200.0M).ToString());
See What every Computer Scientist should know about Floating-Point Arithmetic for further information, or take a look at this website for a simpler explanation.
Here is my test code for some maths I am doing:
Why is C# treating this differently?
EXCEL
Numerator = =-0.161361101510599*10000000
Denominator = =(-1*(100-81.26)) * (10000000/100)
This is most likely due to how the numbers are represented in excel vs. C#. Rounding errors / differences are common when doing artihmatic to a high degree of accuracy on different platofrms or using different software.
EDIT: It could of course be due to different numbers being fed in in the first place. Go me looking for the complex answer!
Programmers are notorious at missing the big picture and overlooking the obvious (well - I am...) Case in point!
Following a comment of you on another answer you say you are obtaining the result (0.8610517689999946638207043757m). If you round it like so:
Math.Round(0.8610517689999946638207043757m, 12);
It will output: 0,861051769000
Your problem is that you are feeding Excel different initial values to your C# code. How do you expect them to be the same?
IOW: 0.161361101510599 != 0.161361102
Not many of us who work on numeric computing trust Excel to add 2 1 digit numbers correctly. I ran your calculation in Mathematica, giving each fractional number 64 digits by extending them to the right with 0s. This is the result:
0.861051771611526147278548559231590181430096051227321237993596585
In this case go with C# rather than Excel. And, on 2nd and 3rd thoughts, in every case go with C# rather than with Excel, whose inadequacies for numeric computing are widely known and well documented.
Excel store 15 significant digits of precision. Read the article "Why does Excel Give Me Seemingly Wrong Answers?".
On another note; you should probably simplify your arithmetic a bit to reduce the number of operations. Generally, (but not always) fewer operations gives a better result in f.p. arithmetic.
val = noiseTerm / (81.26/100 - 1)
is mathematically equivalent to your equation and contains 3 operations as opposed to your 8. In particular, the scalingFactor divides out completely, so it is not necessary at all.
First of all, in most cases Excel uses double precision floating point arithmetic for basic operations just as C# does.
As for your specific case, your C# code does not match your Excel formulas. Try this C# code - which uses your Excel formulas:
static void Calc()
{
double numerator = -0.161361101510599 * 10000000.0;
double denominator = (-1.0 * (100.0 - 81.26)) * (10000000.0 / 100.0);
double result = numerator / denominator;
Console.WriteLine("result={0}", result);
}
Run this and note that the output is 0.861051768999995.
Now, format the result in Excel with the custom number format "0.00000000000000000" and you will see that Excel is giving you the same result as C#. By default, Excel uses the "General" format which rounds this number to ~12 significant digits of precision. By changing to the format above, you force Excel to show 15 digits of precision - which is the maximum number of significant digits Excel will use to display a number (internally, they have 15+ digits of precision just as the C# double type does).
You can force C# to display 15+ significant digits (instead of rounding to 15 significant digits) by running the following code:
static void Calc()
{
double numerator = -0.161361101510599 * 10000000.0;
double denominator = (-1.0 * (100.0 - 81.26)) * (10000000.0 / 100.0);
double result = numerator / denominator;
Console.WriteLine("result={0:R}", result);
}
This code will output 0.8610517689999948...but there is no way AFAIK to get Excel to display 15+ digits.