I am developing .Net 5.0 console application in Visual Studio 2017 Community Edition on Windows 7.
When evaluating this C# code:
int weirdIndex = child.Depth - 1; or similarly int weirdIndex = child._depth - 1; an IndexOutOfRangeException gets thrown.
child is of record type Step, which has a private field _depth as well as a public getter Depth. Here is an extract of this record:
record Step
{
/* a bunch of logic */
private readonly int _depth;
public int Depth => _depth;
}
I tried to use struct instead of record type, but it didn't fix the problem.
weirdIndex later is used to access an array, but the bounds are perfectly fine. Here is an extract from the function where weirdIndex is used:
foreach (var child in AllFather.Children)
levels[child.Depth - 1][levelPtrs[child.Depth - 1]] = child.Sum.ToString();
int weirdIndex = child._depth - 1;
Console.WriteLine("Just separating the lines");
levelPtrs[weirdIndex] = levelPtrs[weirdIndex] + 1;
}
Here is a screenshot of the situation:
I want to point out that the message Just separating the lines actually appears in the Console twice before the Exception is thrown.
I tried evaluating the following expressions in the Watch 1 of the Debug Window, and everything had expected values:
Expression | Value
----------------------------------
levelPtrs[0] | 2
child.Depth - 1 | 0
levelPtrs[child.Depth - 1] | 2
I quickly read IndexOutOfRangeException Class reference by Microsoft, and then also found this thread on StackOverflow: What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?, but neithere of them seem to adress the issue I'm having, as far as my understanding goes.
I am very confused and would really appreciate some help. What am I missing? Is this some kind of bug by any chance?
EDIT: levels is of type string[][], levelPtrs is of type int[], and AllFather.Children is of type Step[].
EDIT: I put all the code in public GitLab repo under the branch "indexoutofrangeexception" in case somebody would like to see the whole codebase. It's not big, but quite noisy. Here is the repo: https://gitlab.com/wizardsanimals/funny-problems .
As #jalepi pointed out in the comments, levels[0] indeed is an array that has not index 2, as it only has a length of 2. That's the reason the exception was thrown.
On line 39 though, not 41. I don't know why Visual Studio decided that the line "int weirdIndex = ..." was the issue, I think it shouldn't have done so. Perhaps it was trying to help.
Thanks everybody for your comments. Moral of the story: check code both below and ABOVE when the cause of exception is unclear.
I am using z3 in visual studio and I want to do a simple check with the following
x > 3
After I run my code, I only get one result back in my model. Why do I only get one result back and how would I do model completion in C#?
Z3 is a satisfiability solver (the S in SMT), i.e., it checks whether there is 1 assignment that satisfies the formula. It can compute sets of solutions in some special cases and if the problems are set up the right way, but without further details I can't tell whether any of this would apply to your problem.
Of course, after getting one satisfying assignment you can add a new constraint that forces the assignment you just got is excluded and then get a new assignment.
Is there a generally accepted best approach to coding complex math? For example:
double someNumber = .123 + .456 * Math.Pow(Math.E, .789 * Math.Pow((homeIndex + .22), .012));
Is this a point where hard-coding the numbers is okay? Or should each number have a constant associated with it? Or is there even another way, like storing the calculations in config and invoking them somehow?
There will be a lot of code like this, and I'm trying to keep it maintainable.
Note: The example shown above is just one line. There would be tens or hundreds of these lines of code. And not only could the numbers change, but the formula could as well.
Generally, there are two kinds of constants - ones with the meaning to the implementation, and ones with the meaning to the business logic.
It is OK to hard-code the constants of the first kind: they are private to understanding your algorithm. For example, if you are using a ternary search and need to divide the interval in three parts, dividing by a hard-coded 3 is the right approach.
Constants with the meaning outside the code of your program, on the other hand, should not be hard-coded: giving them explicit names gives someone who maintains your code after you leave the company non-zero chances of making correct modifications without having to rewrite things from scratch or e-mailing you for help.
"Is it okay"? Sure. As far as I know, there's no paramilitary police force rounding up those who sin against the one true faith of programming. (Yet.).
Is it wise?
Well, there are all sorts of ways of deciding that - performance, scalability, extensibility, maintainability etc.
On the maintainability scale, this is pure evil. It make extensibility very hard; performance and scalability are probably not a huge concern.
If you left behind a single method with loads of lines similar to the above, your successor would have no chance maintaining the code. He'd be right to recommend a rewrite.
If you broke it down like
public float calculateTax(person)
float taxFreeAmount = calcTaxFreeAmount(person)
float taxableAmount = calcTaxableAmount(person, taxFreeAmount)
float taxAmount = calcTaxAmount(person, taxableAmount)
return taxAmount
end
and each of the inner methods is a few lines long, but you left some hardcoded values in there - well, not brilliant, but not terrible.
However, if some of those hardcoded values are likely to change over time (like the tax rate), leaving them as hardcoded values is not okay. It's awful.
The best advice I can give is:
Spend an afternoon with Resharper, and use its automatic refactoring tools.
Assume the guy picking this up from you is an axe-wielding maniac who knows where you live.
I usually ask myself whether I can maintain and fix the code at 3 AM being sleep deprived six months after writing the code. It has served me well. Looking at your formula, I'm not sure I can.
Ages ago I worked in the insurance industry. Some of my colleagues were tasked to convert the actuarial formulas into code, first FORTRAN and later C. Mathematical and programming skills varied from colleague to colleague. What I learned was the following reviewing their code:
document the actual formula in code; without it, years later you'll have trouble remember the actual formula. External documentation goes missing, become dated or simply may not be accessible.
break the formula into discrete components that can be documented, reused and tested.
use constants to document equations; magic numbers have very little context and often require existing knowledge for other developers to understand.
rely on the compiler to optimize code where possible. A good compiler will inline methods, reduce duplication and optimize the code for the particular architecture. In some cases it may duplicate portions of the formula for better performance.
That said, there are times where hard coding just simplify things, especially if those values are well understood within a particular context. For example, dividing (or multiplying) something by 100 or 1000 because you're converting a value to dollars. Another one is to multiply something by 3600 when you'd like to convert hours to seconds. Their meaning is often implied from the greater context. The following doesn't say much about magic number 100:
public static double a(double b, double c)
{
return (b - c) * 100;
}
but the following may give you a better hint:
public static double calculateAmountInCents(double amountDue, double amountPaid)
{
return (amountDue - amountPaid) * 100;
}
As the above comment states, this is far from complex.
You can however store the Magic numbers in constants/app.config values, so as to make it easier for the next developer to maitain your code.
When storing such constants, make sure to explain to the next developer (read yourself in 1 month) what your thoughts were, and what they need to keep in mind.
Also ewxplain what the actual calculation is for and what it is doing.
Do not leave in-line like this.
Constant so you can reuse, easily find, easily change and provides for better maintaining when someone comes looking at your code for the first time.
You can do a config if it can/should be customized. What is the impact of a customer altering the value(s)? Sometimes it is best to not give them that option. They could change it on their own then blame you when things don't work. Then again, maybe they have it in flux more often than your release schedules.
Its worth noting that the C# compiler (or is it the CLR) will automatically inline 1 line methods so if you can extract certain formulas into one liners you can just extract them as methods without any performance loss.
EDIT:
Constants and such more or less depends on the team and the quantity of use. Obviously if you're using the same hard-coded number more than once, constant it. However if you're writing a formula that its likely only you will ever edit (small team) then hard coding the values is fine. It all depends on your teams views on documentation and maintenance.
If the calculation in your line explains something for the next developer then you can leave it, otherwise its better to have calculated constant value in your code or configuration files.
I found one line in production code which was like:
int interval = 1 * 60 * 60 * 1000;
Without any comment, it wasn't hard that the original developer meant 1 hour in milliseconds, rather than seeing a value of 3600000.
IMO May be leaving out calculations is better for scenarios like that.
Names can be added for documentation purposes. The amount of documentation needed depends largely on the purpose.
Consider following code:
float e = m * 8.98755179e16;
And contrast it with the following one:
const float c = 299792458;
float e = m * c * c;
Even though the variable names are not very 'descriptive' in the latter you'll have much better idea what the code is doing the the first one - arguably there is no need to rename the c to speedOfLight, m to mass and e to energy as the names are explanatory in their domains.
const float speedOfLight = 299792458;
float energy = mass * speedOfLight * speedOfLight;
I would argue that the second code is the clearest one - especially if programmer can expect to find STR in the code (LHC simulator or something similar). To sum up - you need to find an optimal point. The more verbose code the more context you provide - which might both help to understand the meaning (what is e and c vs. we do something with mass and speed of light) and obscure the big picture (we square c and multiply by m vs. need of scanning whole line to get equation).
Most constants have some deeper meening and/or established notation so I would consider at least naming it by the convention (c for speed of light, R for gas constant, sPerH for seconds in hour). If notation is not clear the longer names should be used (sPerH in class named Date or Time is probably fine while it is not in Paginator). The really obvious constants could be hardcoded (say - division by 2 in calculating new array length in merge sort).
I've seen in several applications I'm supporting the following sentence:
Random rnd = new Random();
if (rnd.NextDouble() < 1)
{
' Do stuff
}
What could be the purpose of this? rnd is going to return always a value below 1. The only thing I can think of is that if you mock Random then you would be able to deactivate some sections of the code.
What do you think? Have you found things like this?
EDIT: The thing is that this sentences are located on different but related sections of code and always covering entire features. That's why I tend to think that is was coded on purpose. And the code seems to have a certaing degree of quality, it this was a mistake I would be suprised providen all the other code.
I am not sure but this check is not required. rnd.NextDouble will always return in the range
of 0.0 to 1.0.
Random.NextDouble Method - MSDN
A double-precision floating point number greater than or equal to 0.0,
and less than 1.0.
Assuming that the Random in question is indeed System.Random, I can't see any functional reason for having this.
All I could speculate is that perhaps the writer wanted a code block that they could easily (while debugging / developing) run conditionally (by changing the 1 to 0) or only some of the time (by changing the 1 to some value between 0 and 1). But really, this isn't a well-known idiom, so you'd have to ask the person who wrote it, hence my vote to close as too localized.
I have some code that is behaving strangely and seems to be rounding the result of the addition of two double values. This is causing issues with my code.
Unfortunately I cannot fix this issue because my unit testing environment is working OK (not rounding) and my application is not OK (rounding).
In my test environment:
a = -3.7468700408935547
b = 525218.0
c = b + a
c = 525214.25312995911
Inside my application:
a = -3.7468700408935547
b = 525218.0
c = b + a
c = 525214.25
What can be causing this? Project config? (I'm using visual studio, btw)
Edit (from comments)
I'm stepping through the same code using the Visual Studio debugger, so it's the exact same piece of code.
I have more code but I narrowed the problem down to that particular sum.
The binary representations of each value are:
test environment:
System.BitConverter.ToString(System.BitConverter.GetBytes(a)) "00-00-00-00-97-F9-0D-C0" string
System.BitConverter.ToString(System.BitConverter.GetBytes(b)) "00-00-00-00-44-07-20-41" string
System.BitConverter.ToString(System.BitConverter.GetBytes(c)) "00-40-9A-81-3C-07-20-41" string
inside application:
System.BitConverter.ToString(System.BitConverter.GetBytes(a)) "00-00-00-00-97-F9-0D-C0" string
System.BitConverter.ToString(System.BitConverter.GetBytes(b)) "00-00-00-00-44-07-20-41" string
System.BitConverter.ToString(System.BitConverter.GetBytes(c)) "00-00-00-80-3C-07-20-41" string
Edit 2:
As Alexei Levenkov points out, this issue is caused by a library that changes the FPU config.
For anyone who is curious what this meant for me:
I was able to mitigate this issue for my particular piece of code, by making some assumptions about my input values and doing some preemptive values rounding which in turn made my calculations consistent.
Your application may be doing something strange with configuration of FPU. I.e. using some random library for math which reconfigures precision...
Direct3d is possible suspect, see for example Pow implementation for double.
Use decimal if one wants preciscion such as needed in financial calculations.
Edit
See:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Five Tips for Floating Point Programming