Why Didn't This Condition Trigger? - c#

I have a robot stock trading program that I've been working on for a few months. The other day though I added a 2nd condition to the code that determines when the trade gets exited. Condition as follows:
decimal entryPrice;
decimal CurrentPrice;
decimal openShares;
if ((1st condition) && (((entryPrice - CurrentPrice) * openShares) >= 8))
Today was the first day the situation came up, and I happened to have the day off work so I was observing the trades. The condition didn't trigger though. The trade kept going until I manually exited.
What should have happened is that it would subtract the current price from the price at time of entry, then multiply that by the number of shares to get the current profit. And if it's greater than or equal to 8, it triggers. This particular code was only for exiting short trades, so subtracting the current price from the entry price should return a positive value.
I verified in my code that the entryPrice was being logged at time of purchase. So all I can think is that I'm messing something up with the condition format. Either it doesn't like the bracket arrangement or the resulting number value types aren't compatible with each other. Does anything jump out at you? Thanks.

Not sure about the exact cause, but if your "1st condition" is false, the second condition will not be evaluated at all for many languages.
So please make sure the '1st condition' is true.
After that, if the problem still exist, you can print out some log messages about the variable values to see what's going on.

Change your conditional to
if(true){
//code after the conditional
}
If this executes, Then something isn't getting set properly inside your brackets.
(((entryPrice - CurrentPrice) * openShares) >= 8)
This is your second part of the condition. Parenthesis match up, however, I do not know what's happening inside the conditional. Since you're multiplying, it very easily could be constantly greater than 8. (maybe you meant less than?)
Try printing out some values, and see where that leads you. Print out your first condition, then your second condition.
If you have support for implicit conversions, try using BITWISE AND (&) rather than LOGICAL AND (&&).
This way, the second condition will be 'resolved' to a variable. (i.e. ran)

Related

Getting random numbers after a simple math problem. Might be a local variable thing

I have a GUI working on the front end. But on the back end I have a little problem with my math. Code is trying to calculate how much time has gone with only starting and ending hours. (There are no info on days). So I think I found the way to calculate the hours spent on paper. But in C# I failed I think because of local variable stuff.
float start = float.Parse(textBox1.Text);
float end = float.Parse(textBox2.Text);
float hours_spent = end - start;
if (start > end) {
hours_spent = 24.00f -start + end;
}
First part is working correctly but when I give the start bigger than end, it gives me random numbers.
EDIT: When i gave 14.00 as an input and 13.00 as an output i get -76
and for input 14.00 output 12.00 i get -176 and for 18.50 to 10.25 i get -801. It is not random i can see that too my bad on choosing the words. But i dont get it what is wrong
When i gave 14.00 as an input and 13.00 as an output i get -76
You are parsing in a part of the world where . is not the decimal separator but is a common "group" separator. That is, a number like one hundred thousand plus a quarter is written 100.000,25, and not as it would be in the United States, 100,000.25. Parse assumes that the string is in the format of the current user's locale unless you tell it otherwise.
Therefore you are parsing the strings into values 1400 and 1300. Their difference is -100, which is less than 0, so you add 24 to -100 and get -76.
Same for your other case. You have 1850 and to 1025, subtract them to get -825, add 24 and you get -801.
There's nothing "random" at all here; everything is working as expected.
There is a lesson here: work backwards. You got -76. How'd that happen? You must have added 24 to something. What added to 24 gives you -76? -100. How did we get -100? And so on.
Start over. You should not be parsing floats in the first place. If this is a decimal quantity then you should be parsing a decimal, and if you know that it will always have . as the decimal separator, you should say so when you parse it. (Hint: use the version of TryParse that takes a NumberStyles and set the style correctly.)
If, on the other hand, you know that this is two integers separated by a period, then you should not be parsing it as a decimal or a float. You should be parsing an integer, then a period, then an integer.
If this is hours then a period then minutes, then again, you should not be using any of the above. Use a date and time parser to parse dates and times.
In short: use the right tool for the job you actually have to do.
Other problems with your code:
Use TryParse, not Parse, when dealing with user input. You don't know that there is a valid number in there, but Parse will crash if it gets bad input.
Your math is probably wrong. If someone puts in 100 and 200, do you really want -76 as the output?
Take a step back and ask yourself what the real business process is that you're trying to build here. Write that business process down carefully and then implement that process, not an approximation of it. Your business process probably does not say "parse a float using the rules of the current locale" but that's the code you wrote. Write code that means exactly what you intend it to mean.
UPDATE: Comments on the question indicate just how deep a hole you've gotten yourself into:
If entry time is 13.55 and exit time is 14.05 what should be the expected logical result ? It should be 10 (minutes) or 50 (numeric difference) ?
I am expecting 10 as minutes
Then absolutely you should not be parsing as float or decimal! Parsing as float or decimal is obviously completely wrong because 1.1 and 1.10 are the same value as a number, but nine minutes different if it is "hours.minutes", and you can't tell which case you are in by parsing as a number.
Again, you need to stop writing code, erase everything you've written so far, and start over. You're in a hole: stop digging deeper, fill in the hole, and get back to ground level.
You need to figure out exactly what format your strings are in, and parse exactly that format and nothing else.
So, write a specification that poses and then answers questions about what is allowed and what is not. Are negative values allowed? What if the number of minutes is more than 60? What if the minutes or hours are missing entirely? And so on.
Once you have a specification, write test cases that verify the spec. Then write an implementation, and run your tests. The code is more likely to be correct if you write the tests first.
I'm going to completely ignore providing a didactic answer in favor of trying to sidestep the problem.
Avoid writing your own parsing code. Instead, replace all your TextBoxes with DateTimePickers with Format set to Time. Then pull out the time by calling the .Value.TimeOfDay property. TimeOfDay is a TimeSpan, so it supports simple arithmetic.
Warning: Watch out when pulling these results using the provided properties. For example, 150 minutes can be translated as either 2 .Hours and 30 .Minutes or to 150 .TotalMinutes .

Two inline Condition Check

i am trying to avoid extra lines of code. so i am running this by you guys to see if it correct. i wrote an inline condition to check for 2 elments in an object.
if the Notification Date (EndsAt) is assigned and the errormessage is NullorEmpty or the Notification Date is not assigned and the errormessage is not NullorEmpty then return "09".
if ((Notification.EndsAt.HasValue && String.IsNullOrEmpty(Notification.ErrorMessage)) || (!Notification.EndsAt.HasValue && !String.IsNullOrEmpty(Notification.ErrorMessage)))
{
return "09";
}
thanks for your help.
What exactly is your question?
Are my conditions correct in checking 2 elements?
If you're asking if your conditions are correct and do what you ask them to do, then that looks OK. The parentheses and bangs go where they should.
Is there any way I can reduce the condition checks?
Can't answer that since you didn't mention what you want to return for cases where:
EndsAt is not Assigned & ErrorMessage IS NullorEmpty
EndsAt is assigned & ErrorMessage IS NOT NullorEmpty
Can I improve performance and readability?
Since the conditional logic here depends on whether EndsAt hasValue and if ErrorMessage is null or empty, you could just store them in variables and compare those variables with the boolean logic you supplied. This reduces length of code (and improves readability), and if getting those boolean values multiple times in your program takes awhile, having them as local variables will improve performance. (think about how saving the count of elements in an array and using it multiple times (while it remains unchanged) is more efficient than calling the count method multiple times when you know the count won't change.

Does the order of appearance matter in a single IF statement with multiple conditions

I've got a Collection with up to 19,000 entries in it that I'm iterating over in a foreach statement. At the beginning of the foreach, I check if a string contains 1 of 2 words and a boolean value, then I either continue or perform some more operations.
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if ((e.Path.Contains("bin") ||
e.Path.Contains("obj")) && !includeBinObjFolders)
continue;
//Do a bunch of things
}
I wasn't sure if the computer would check the string for either "bin" or "obj", and then check the boolean and maybe it'd realize it didn't matter that the strings contained one of those two 'key words'.
Basically I guess what I'm saying is would the following take a different amount of time to run?
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if (!includeBinObjFolders &&
(e.Path.Contains("bin") ||
e.Path.Contains("obj")
)
)
continue;
//Do a bunch of things
}
For some reason, I hear a voice in the back of my head telling me that it evaluates the right-most expression first, and works its way left. If so, the first should be more efficient right? I don't have an easy way of testing a collection larger than ~200 files so simply using a timer yields results that are so close I can't confirm if one way is better.
Frankly I think it's highly unlikely end users will encounter more than 500 pieces of data in this collection at most, but theoretically it could happen due to user error.
Edit thanks everyone. I tried searching around before posting here but I forgot the term "short circuiting" in regards to logic so I was having a tough time finding an answer relevant to my wordy title here.
Edit 2 Actually I just went and created a small console application that had a 2 for loops iterating 20,000 times each. One tested the Contains first, the other tested the Bool first. Repeating these two loops 10 times over, it looks like the boolean first takes on average half of a millisecond per 20K iterations. The Contains being evaluated first takes roughly 3 milliseconds per 20K iterations. A small difference indeed!
The given boolean expressions will be evaluated from left to right, not right to left. The order is indeed defined; it is not arbitrary, nor can it be optimized. It will always be left to right.
This was specifically called out in the specs so that the side effects of each expression are always executed in a defined order.
You can, if you want, move the boolean variable to the front as an optimization. It may not be a huge optimization, so don't fret too much over it, but it is an optimization. (Unless of course you know that it will always, or almost always, resolve to true while another expression would resolve to false.)
The last expression would probably save you a little more on the runtime as you are only computing a boolean value first. If that's false, the rightmost expression won't even get evaluated, since false AND anything will be false.
Logical operators are processed left to right and && and || are shortcircuit operators; meaning
x || y // will evaluate x and if it's false, then it will evaluate y
x && y // will evaluate x and if it's true, then it will evaluate y
http://msdn.microsoft.com/en-us/library/aa691310(v=vs.71).aspx
your second approach would be faster
In this example, you are short-circuiting your evaluation using &&:
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if (!includeBinObjFolders &&
(e.Path.Contains("bin") ||
e.Path.Contains("obj")))
continue;
//Do a bunch of things
}
So basically, if !includeBinObjFolders = true stop evaluating.
And in this example, you are using || to evaluate the first two conditions; and if one of them is true you will stop evaluation.
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if ((e.Path.Contains("bin") ||
e.Path.Contains("obj")) && !includeBinObjFolders)
continue;
//Do a bunch of things
}
I honestly don't think either would be noticably faster than the other. Oh, and as an aside, evaluation is left-to-right, and never right-to-left.

c# logic error in a while-loop entering condition

I have some weird logic stuff going on.
x=false;
This one does not work:
while (R2.TS("a") && R2.TL("b") && (s=R2.SL().Trim()).Length > 0)
{
x=true;
}
result: x=false;
This one does work:
while (R2.TS("a") && R2.TL("b"))
{
if((s=R2.SL().Trim()).Length > 0)
{
x=true;
}
}
result: x=true;
Also, maybe it helps to know that those functions return true only if executed in right order, like R2.TS("a") then R2.TL("b") and then ((s=R2.SL().Trim()).Length > 0).
input is the same, but something is surely wrong here. Any ideas ?
thanks in advance.
Yes, the loops do two different things.
I think you mean a logic error, not a syntax error. Syntax error means it won't compile. Logic error means it doesn't do what you expect.
The first one will terminate if the R2.SL() expression is false. At least the first time round, (s=R2.SL().Trim()).Length > 0 must necessarily be false, so loop 1 terminates and x is never set to true. That is the only way you would get a difference between your two loops, all other conditions being the same.
In loop 2, intermediate values for R2.SL() isn't a problem, provided the other loop conditions remain true. When (s=R2.SL().Trim()).Length > 0 evaluates to true, x will be set.
Use the debugger luke. There is little point us trying to work out why this doesn't give you the result you want. It is better for you to work that out with some help. Click on the first line and push F9. It should turn red. Run your program and it will stop at this line. You can then hover over different variables to see which ones have which values. Then push F11 to step forward through your program.
In the first case have three conditions to which R2 has to comply namely
R2.TS("a") AND R2.TL("b") AND (s=R2.SL().Trim()).Length > 0), before you will enter the loop and return the value of x
In the 2nd case you only have two conditions to which R2 has to comply namely
R2.TS("a") AND R2.TL("b") and after the loop is entered, you have a new condition before the x value is returned.
They probably both work, but in the first case, you don't supply data which complies to the requirements of the loop.
It may be connected with && and || operations. They are shortaned. It means, that operations are looked continuously utill the first false occurs in the condition.
Because of shortaned operations you get 2 different cycles, which have different logics. Use the 2 cycle type. It's more correct.

Changing variables outside of Scope C#

I'm a beginner C# programmer, and to improve my skills I decided to give Project Euler a try. The first problem on the site asks you to find the sum of all the multiples of 3 and 5 under 1000. Since I'm essentially doing the same thing twice, I made a method to multiply a base number incrementally, and add the sum of all the answers togethor.
public static int SumOfMultiplication(int Base, int limit)
{
bool Escape = false;
for (int mult = 1; Escape == true; mult++)
{
int Number = 0;
int iSum = 0;
Number = Base * mult;
if (Number > limit)
return iSum;
else
iSum = iSum + Number;
}
regardless of what I put in for both parameters, it ALWAYS returns zero. I'm 99% sure it has something to do with the scope of the variables, but I have no clue how to fix it. All help is appreciated.
Thanks in advance,
Sam
Your loop never actually executes:
bool Escape = false;
for (int mult = 1; Escape == true; mult++)
Escape is set to false initially, so the first test fails (Escape == true returns false) and the body of the loop is skipped.
The compiler would have told you if you were trying to access variables outside of their defined scope, so that's not the problem. You are also missing a return statement, but that is probably a typo.
I would also note that your code never checks if the number to be added to the sum is actually a multiple of 3 or 5. There are other issues as well (for example, iSum is declared inside of the loop and initialized to 0 after each iteration), but I'll let you work that one out since this is practice. The debugger is your friend in cases like these :)
EDIT: If you need help with the actual logic I'll be happy to help, but I figure you want to work it out on your own if possible.
As others have pointed out, the problem is that the control flow does not do what you think it does. This is a common beginner problem.
My suggestion to you is learn how to use your debugger. Beginners often have this strange idea that they're not allowed to use tools to solve their coding problems; that rather, they have to reason out the defect in the program by simply reading it. Once the programs become more than a page long, that becomes impossible for humans. The debugger is your best friend, so get to know its features really well.
In this case if you'd stepped through the code in the debugger you'd see that the loop condition was being evaluated and then the loop was being skipped. At that point you wouldn't be asking "why does this return zero?", you'd be asking "why is the loop body always skipped?" Clearly that is a much more productive question to ask since that is actually the problem here.
Don't write any code without stepping through it in the debugger. Watch every variable, watch how it changes value (the debugger highlights variables in the watch windows right after they change value, by the way) and make sure that the control flow and the variable changes are exactly as you'd expect. Pay attention to quiet doubts; if anything seems out of the ordinary, track it down, and either learn why it is correct, or fix it until it is.
Regarding the actual problem: remember that 15, 30, 45, 60... are all multiples of both three and five, but you only want to add them to the sum once. My advice when solving Project Euler problems is to write code that is as like what you are trying to solve as is possible. Try writing the problem out in "pseudocode" first. I'd pseudocode this as:
sum = 0
for each positive number under 1000:
if number is multiple of three or five then:
add number to sum
Once you have that pseudocode you can notice its subtleties. Like, is 1000 included? Does the problem say "under 1000" or "up to 1000"? Make sure your loop condition considers that. And so on.
The closer the program reads like the problem actually being solved, the more likely it is to be correct.
It does not enter for loop because for condition is false.
Escape == true
returns false
Advice:
Using for loop is much simpler if you use condition as limit for breaking loop
for (int mult = 1; something < limit; mult++)
This way in most cases you do not need to check condition in loop
Most programming languages have have operator modulo division.
http://en.wikipedia.org/wiki/Modulo_operation
It might come handy whit this problem.
There are several problems with this code. The first, and most important, is that you are using the Escape variable only once. It is never set to false within your for loop, so it serves no purpose whatsoever. It should be removed. Second, isum is declared within your for loop, which means it will keep being re-initialized to 0 every time the loop executes. This means you will only get the last multiple, not the addition of all multiples. Here is a corrected code sample:
int iSum = 0;
for(int mult = 1; true; mult++)
{
int Number = Base * mult;
if(Number > limit)
return iSum;
else
iSum += Number;
}

Categories

Resources