I have a stream of decimals and I am trying to compare the most recent decimal to the difference of the last 6 decimals, I may increase this number
I have the following class
public class CompareRandom
{
private const decimal DIFFERENCE = 1.8m;
public decimal a;
public decimal b;
public decimal c;
public decimal d;
public decimal e;
public decimal f;
public decimal g;
public bool Compare(decimal num)
{
this.g = this.f;
this.f = this.e;
this.e = this.d;
this.d = this.c;
this.c = this.b;
this.b = this.a;
this.a = num;
if (b != decimal.Zero && b / DIFFERENCE > a)
{
return true;
}
if (c != decimal.Zero && c / DIFFERENCE > a)
{
return true;
}
if (d != decimal.Zero && d / DIFFERENCE > a)
{
return true;
}
if (e != decimal.Zero && e / DIFFERENCE > a)
{
return true;
}
if (f != decimal.Zero && f / DIFFERENCE > a)
{
return true;
}
if (g != decimal.Zero && g / DIFFERENCE > a)
{
return true;
}
return false;
}
}
Then I initialize it as volatile
volatile static CompareRandom CompareRandom = new CompareRandom();
Then I call CompareRandom.Compare(value) synchronously as part of a loop that updates every 1ms to compare the values.
The part I am the most interested in knowing if there is a faster way to do is this part
this.g = this.f;
this.f = this.e;
this.e = this.d;
this.d = this.c;
this.c = this.b;
this.b = this.a;
this.a = num;
A successful answer will demonstrate a faster execution of the method Compare
See if you can make it faster:
https://dotnetfiddle.net/tLw8qM
https://dotnetfiddle.net/jd0bSF
You don't need to perform the division every time. Instead, multiply a by DIFFERENCE to obtain a threshold:
// Name changed to be more conventional
private const decimal Difference = 1.8m;
public bool Compare(decimal num)
{
g = f;
f = e;
e = d;
d = c;
c = b;
b = a;
a = num;
var threshold = num * Difference;
return (b != decimal.Zero && b > threshold) ||
(c != decimal.Zero && c > threshold) ||
(d != decimal.Zero && d > threshold) ||
(e != decimal.Zero && e > threshold) ||
(f != decimal.Zero && f > threshold) ||
(g != decimal.Zero && g > threshold);
};
As asides:
It's odd for a Compare method to return bool rather than an integer; given that it's not the "common" meaning of Compare, it's probably worth renaming it for clarity
It's very odd for a comparison method to change the state of an object, as this is doing (assigning to a) - another good reason to change the name.
Using a collection instead of separate variables would make all of this more maintainable, but I'd be surprised if it improved the speed.
I also really like the idea of eliminating the division, but I don't like the way you're handling booleans: the original question says something like:
if condition1 then return true;
if condition2 then return true;
if condition3 then return true;
If condition1 is true, then the code does not bother about the calculation of the other conditions (why would it, when one condition is true, then the OR of all conditions also is true).
The proposal from Jon looks as follows:
return (condition1 || condition2 || condition3)
This does exactly the same thing, but the fact if the calculation of the OR equation is determined by the compiler: if you're dealing with an older compiler, not performing optimsation, then the entire calculation is done, even if condition1 is true.
Related
I'm trying to understand how it is possible to put condition inside condition itself.
for example, below I'm showing wrong unreal code, but clear to understand what I'm asking for without extra words:
if (a == 1 && if (b == 1) { c >= 5 })
{
/// process
}
So condition c >= 5 must be taken into the account for process only in case if b == 1 which must be exist inside one statement without using of separate function with separate conditions or as condition after condition.
Question is how take part of condition into the account inside the condition only in case if some value is true and avoid it if false and read only a == 1.
EDIT based on answer below:
int a = 1;
int b = 0;
int c = 6;
if (a == 1 && (b != 0 || c >= 5))
{
Console.WriteLine("yes");
if (c > 5)
{
Console.WriteLine("taken into the account");
}
}
else
{
Console.WriteLine("no");
}
in both cases int b = 1; and int b = 0; result is:
yes
taken into the account
desired result:
in case of int b = 1; :
yes
taken into the account
and in case of int b = 0;:
yes
if (a == 1 && (b != 1 || c >= 5 ))
Here, c >= 5 will only be evaluated when b==1.
In c# && is a short circuiting operation so b==1 will not be evaluated if a==1 does not evaluate to true.
I want to convert a string expression to a real boolean expression.
The expression below will be an input (string):
"(!A && B && C) || (A && !B && C) || (A && B && !C) || (A && B && C)"
The variables A, B and C will have your boolean values (true or false).
How I can transforming a string expression, replace the logic values and validate using C#?
If you don't want to use some available libraries to parse that string you need to separate those characters and implement the logic based on comparison. So for example say we have "a || b", we can loop though each character and decide the appropriate operation based on char == '|'. For more complex situation I'd use a stack to keep track of each results, like this one that can handle && and || without parentheses:
public bool ConvertToBool(string op, bool a, bool b)
{
var st = new Stack<bool>();
var opArray = op.ToCharArray();
var orFlag = false;
var andFlag = false;
for (var i = 0; i < opArray.Length; i++)
{
bool top;
switch (opArray[i])
{
case '|':
i++;
orFlag = true;
break;
case '&':
i++;
andFlag = true;
break;
case 'a':
if (orFlag)
{
top = st.Pop();
st.Push(top || a);
orFlag = false;
}
else if (andFlag)
{
top = st.Pop();
st.Push(top && a);
andFlag = false;
continue;
}
st.Push(a);
break;
case 'b':
if (orFlag)
{
top = st.Pop();
st.Push(top && b);
orFlag = false;
}
else if (andFlag)
{
top = st.Pop();
st.Push(top && b);
andFlag = false;
continue;
}
st.Push(b);
break;
}
}
return st.Pop();
}
I have a list of items that I need to validate. The list can contain any number of items of the type A, B and C, but before the list can be saved, it must confirm to the following rules:
If you have A, you need either B or C
If you have B, you need A
I have ended up with the following code (saudo code):
bool IsListValid()
{
var a = list.ContainsAny(A);
var b = list.ContainsAny(B);
var c = list.ContainsAny(C);
if (!a && !b)
return true;
if (a && (b || c)
return true;
return false;
}
I don't like this code.
1. The use of Any three times in a row will potentially iterate the list three times
2. The if's doesn't look good to me.
Of cause it would be better with different variable names and by extracting the test into methods with good names, but I think there are better ways of solving this entirely. I'm just not sure how...
Any tips?
I would use a simple loop, it's both, comprehensible and efficient.
bool containsA = false, containsB = false, containsC = false;
for (int i = 0; i < list.Count; i++)
{
Type itemType = list[i].GetType();
if (!containsA) containsA = itemType == typeof(A);
if (!containsB) containsB = itemType == typeof(B);
if (!containsC) containsC = itemType == typeof(C);
if (containsA && (containsB || containsC)) return true;
}
return (!containsA && !containsB);
If it's so important that you only go through the list once, you could do this:
bool a = false;
bool b = false;
bool c = false;
foreach(var x in list)
{
if (x is A) a = true;
if (x is B) b = true;
if (x is C) c = true;
}
But I'd leave it as it is. If profiling later shows that this code is becoming a bottleneck, you can revisit it then.
As for the if's, that looks fine to me. As long as A, B and C are properly named (something like hasNotifyEmail or needsResponse, something that explains why you want them to work with the specified rules) then it should be easy for others to understand.
var hasA = list.Any(x => x.GetType() == typeof(A));
var hasB = list.Any(x => x.GetType() == typeof(B));
var hasC = list.Any(x => x.GetType() == typeof(C));
//If you have A, you need either B or C
// A AND (B xor C)
if (hasA && (hasB ^= hasC))
return true;
//If you have B, you need A
if (hasB && hasA)
return true;
return false;
How do I compare complex types in queries?
Does not work (always returns null, EDIT: since new version of EF it throws exception):
DbVector3 pos = new DbVector3() { X = 0, Y = 0, Z = 0};
db.PhysObjects.FirstOrDefault(s => s.Position == pos);
Works:
DbVector3 pos = new DbVector3() { X = 0, Y = 0, Z = 0};
db.PhysObjects.FirstOrDefault(s => s.Position.X == pos.X && s.Position.Y == pos.Y && s.Position.Z == pos.Z);
Is there any way to make first example working?
EDIT:
Sorry, I probably mention only in title that this is entity framework.
db is ObjectContext, PhysObjects is ObjectSet<>
You need to override the Equals function in your DbVector class, so that when comparisons are made it will be used to compare 2 objects.
protected override bool Equals(object comparer)
{
DbVector3 compareObj = obj as DbVector3;
return compareObj.X == this.X && compareObj.Y == this.Y && compareObj.Z == this.Z;
}
You can also do the same for the == and != operators. Something similar to below :
public static bool operator ==(DbVector3 a, DbVector3 b)
{
return a.X == b.X && a.Y == b.Y && a.Z == b.Z;
}
public static bool operator !=(DbVector3 a, DbVector3 b)
{
return !(a == b);
}
Have a read of MSDN - Guidelines for Overriding for more information.
No, it's not supported, unless both values are in database.
Is there a quick way to compare equality of more than one values in C#?
something like:
if (5==6==2==2){
//do something
}
Thanks
if (a == b && b == c && c == d) {
// do something
}
In C#, an equality operator (==) evaluates to a bool so 5 == 6 evaluates to false.
The comparison 5 == 6 == 2 == 2 would translate to
(((5 == 6) == 2) == 2)
which evaluates to
((false == 2) == 2)
which would try to compare a boolwith an int. Only if you would compare boolean values this way would the syntax be valid, but probably not do what you want.
The way to do multiple comparison is what #Joachim Sauer suggested:
a == b && b == c && c == d
public static class Common {
public static bool AllAreEqual<T>(params T[] args)
{
if (args != null && args.Length > 1)
{
for (int i = 1; i < args.Length; i++)
{
if (args[i] != args[i - 1]) return false;
}
}
return true;
}
}
...
if (Common.AllAreEqual<int>(a, b, c, d, e, f, g))
This could help :)
No this is not possible, you have to split it into separate statements.
if(x == y && x == z) // now y == z
{
}
Good luck