Is it possible to re-write the following so that it doesn't contain any conditional statements? I'm thinking there might be some clever trick using something like bitwise operations?
int a = // some value
int b = // some other value between 0 and max int
if(b >= 3)
{
return a + 1;
}
else
{
return a;
}
EDIT: to be clear, I'm not looking for a generic way of removing conditionals. I'm looking for a trick to remove the conditionals from this very specific code. Think of it as an academic puzzle.
To give an example, one way to remove conditionals (which happens to yield perf gains in some situations) is to precompute a lookup table and index into that with b instead. In this particular case this is tricky because b could be a very large number. Is there another way?
Here you go
return a - ((2 - b) >> 31);
Explanation:
r = 2 - b, < 0 (i.e. high bit set) for b >= 3
r >> 31, = -1 for b >= 3, 0 otherwise
uint a = // some value
uint b = // some other value between 0 and max int
bool c = b & 0xFFFC
return a + Convert.ToInt32(c);
The fastest will probably be as bitwise operations tend to be very fast
uint a = // some value
uint b = // some other value between 0 and max int
return (b & 0xFFFC) ? a+1 : a;
You could make it better by doing this:
int a = // some value
int b = // some other value between 0 and max int
return (b >= 3) ? (a+1) : a;
?: operator. (but yet it contains conditional statement.)
return b >= 3 ? a + 1 : a;
or
return a + (b >= 3 ? 1 : 0);
Is it possible to re-write the following so that it doesn't contain any conditional statements?
It is not possible to make it work out of no where. you must check this condition any way. There is no magic.
If you want to make your program faster by removing this condition then you picked wrong way. this is micro optimization.
Related
I been searching for some information about if statements with multiple conditions but haven't found something that corresponds to myquestion.
I was wondering if you could write:
int n = 3
if (3 < n < 20)
{
//do something..
}
rather than doing:
if (n > 3 && n < 20)
{
//do something..
}
The first statement doesn't work for me which i think it should, because it's plain simple.
Maybe someone can give me the correct syntax for doing so or maybe it's just impossible at all and i just have to go with the AND.
To explain why it's invalid:
if (3 < n < 20)
Could be rewritten as:
if ((3 < n) < 20)
Now 3 < n's outcome would be a bool.
So basically you'll get:
if (true/false < 20)
Which is not valid in C#.
Stefan's answer explains why it's impossible.
But here is a workaround, if you don't want to write that pesky && explicit conditions every time - you can create an extension method:
public static class IComparableExtensions
{
public static bool Between<T>(this T self, T low, T high) where T : IComparable
{
return self.CompareTo(low) > 0 && self.CompareTo(high) < 0;
}
}
And use it like this:
int n = 5;
if(n.Between(3, 20))
{
// do your stuff here
}
Please note, however, that this might be confusing - since Between doesn't specify if the compare is inclusive, exclusive, or inclusive in only one direction - so if you compare, say, 20.Between(10, 20) - should it return true or false?
A better approach would require adding another variable to the method, to indicate that:
[Flags]
public enum CompareMode
{
Exclusive = 0,
IncludeLow = 1,
IncludeHigh = 2,
Inclusive = IncludeLow | IncludeHigh
}
public static class IComparableExtensions
{
public static bool Between<T>(this T self, T low, T high, CompareMode mode) where T : IComparable
{
var compareLow = (mode & CompareMode.IncludeLow) == CompareMode.IncludeLow ? 0 : 1;
var compareHigh = (mode & CompareMode.IncludeHigh) == CompareMode.IncludeHigh ? 0 : -1;
return self.CompareTo(low) >= compareLow && self.CompareTo(high) <= compareHigh;
}
}
Now you use it like this:
if(n.Between(3, 20, CompareMode.Exclusive))
{
// do your stuff here
}
You can see a live demo on rextester.
This way, another person reading this code (or even you, 6 months from now) will know immediately, without having to look inside the Between extension method, if between is inclusive, exclusive, or whatever.
Generally it is not possible what you want to do.
but in your logic if you want to perform single liner logic you can use ternary operator.
for eg. you need to assign value of n to variblae result else it should be 0 as default.
int result = n > 3 ? (n < 20 ? n : 0) : 0
it is equivalent to
int result = 0;
if (n > 3 && n < 20)
{
result = n;
}
Say we have two values,
int a = 2489;
int b = 3019201;
From these two values i want to create an if statement to check if the two values have the same ones digit. i.e. 248(9) and 301920(1). In this case they dont obviously.
But i want to make an if to check this, how would i go ahead and do this?
Check if the difference of a and b is divisible by 10 without remainder (modulo):
bool hasSameOnes = (a - b) % 10 == 0
Use the modulo operator:
if ( (a%10) == (b%10) )
{
}
Is there an easy, efficient and correct (i.e. not involving conversions to/from double) way to do floored integer division (like e.g. Python offers) in C#.
In other words, an efficient version of the following, that does not suffer from long/double conversion losses.
(long)(Math.Floor((double) a / b))
or does one have to implement it oneself, like e.g.
static long FlooredIntDiv(long a, long b)
{
if (a < 0)
{
if (b > 0)
return (a - b + 1) / b;
// if (a == long.MinValue && b == -1) // see *) below
// throw new OverflowException();
}
else if (a > 0)
{
if (b < 0)
return (a - b - 1) / b;
}
return a / b;
}
*) Although the C# 4 spec of the Division operator leaves it open whether OverflowException is raised inside unchecked, in reality it does throw (on my system) and the Visual Studio .NET 2003 version even mandated it throw:
If the left operand is the smallest representable int or long value and the right operand is –1, [..] System.OverflowException is always thrown in this situation, regardless of whether the operation occurs in a checked or an unchecked context.
Edit
The crossed out statements about checked and unchecked are all nice and well, but checked is in fact only a compile time concept, so whether my function should wrap around or throw is up to me anyway, regardless of whether code calling the function is inside checked or not.
You can try this:
if (((a < 0) ^ (b < 0)) && (a % b != 0))
{
return (a/b - 1);
}
else
{
return (a/b);
}
Edit (after some discussions in comments below):
Without using if-else, I would go like this:
return (a/b - Convert.ToInt32(((a < 0) ^ (b < 0)) && (a % b != 0)));
Note: Convert.ToIn32(bool value) also needs a jump, see implemention of the method:
return value? Boolean.True: Boolean.False;
Theoretically, it is not possible to calculate the division for a = long.MinValue and b = -1L, since the expected result is a/b = abs(long.MinValue) = long.MaxValue + 1 > long.MaxValue. (Range of long is –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.)
The way it works in any sane programming language (one that follows our normal order of operations) is that -1.0/3.0 is equivalent to -(1.0/3.0) which is -0.3333.... So if you want that converted to an int, it's really the cast/floor operator you need to think about, not the division. As such, if you want this behavior, you must use (int)Math.Floor(a/b), or custom code.
You don't need to implement this yourself, the Math class provides a builtin method for doing Euclidean division: Math.DivRem()
The only downside is that you have to provide an assignable variable for the remainder:
long remainder;
long quotient = Math.DivRem(a, b, out remainder);
I'm making a piece of code that takes the fibonacci sequence below 4 000 000 and sums up the even numbers. in order to do this I made an easy piece of code that should work but the "C" variable goes over the 4 000 000 where it shouldn't (it ends on the number:"5 702 887"), as you can see here:
int amount = 4000000;
int A = 1;
int B = 2;
int C = 0;
int answer = 0;
while (C < amount)
{
C = A + B;
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
}
You're modifying C after you check its value. The operator is working as expected.
Your while condition is being evaluated when C = 3524578, then you're incrementing it to the >5,000,000 number, using it, and checking again.
Remember that while loops will always exit when the condition is false.
You should probably adjust the order of your tests. For instance,
int amount = 4000000;
int A = 1;
int B = 2;
int C = 3; // I've changed this to give an appropriate start value
int answer = 0;
while (C < amount)
{
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
C = A + B; // I've moved this so that answer is not in between the altering of this value and the check for it.
}
You could also implement a for loop, which will perform this action in a bit more language-native way.
int amount = 4000000;
int A = 1;
int B = 2;
int answer = 0;
for (int C = 3; C < amount; C = A + B)
{
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
}
The difference here is that the predicate expression is evaluated every time C is set.
I'm in an analogy mood, and I don't think I really explained the actual bug here as much as I just gave the proper code to resolve the issue (teach a man to fish, as they say), so here's a real world example of a flaw in logic like this.
Let's say you're eating orange slices and you absolutely hate seeds and want nothing to do with any oranges that contain them. Regularly, you'd pick one up, check it for seeds, and eat it if it's clear. If you come across one with seeds in it, then gross, and throw away all your remaining orange slices. In pseudo-code, while (the next one doesn't have any seeds) { eat it and grab another. }. Simple enough, right?
However, the way you've written your while loop here, you'd be eating a slice, finding seeds in your mouth, then throwing them away. And as you can see, these are very different situations.
This latter one houses folds of regret because you checked the slice (the variable) after eating (using) it, rather than before. You know not to eat any more, sure, but you've already eaten a seed. You would have been much better off to check it before you ate it, since then you'd have known it was contaminated before it came anywhere near your mouth.
I suspect that you have a false belief common to beginners. The while statement does not terminate the loop immediately the moment that the condition is violated.
The correct way to think about a while loop is that
while(condition)
statement
is logically the same thing as:
continue_label:
if (!condition) goto break_label;
statement
goto continue_label;
break_label:
The condition of a while loop is executed only while entering the loop each time. If you look at your code, C is assigned after this check. Try printing C just before your C = ... assignment - you will see that it does not go beyond the limit.
The next assignment exceeds the value, but the while loop is not entered again.
When C is checked its still bellow 4000000 but then inside the iteration it gets raised above the limit(C = A + B) and in the next iteration its above that value and the loop exits.Instead try this "very dirty" implementation:
int amount = 4000000;
int A = 1;
int B = 2;
int C = 0;
int answer = 0;
for (int i = 0; i < amount; i = A + B)
{
C = A + B;
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
}
I was looking for an efficient approach for calculating ab (say a = 2 and b = 50). To start things up, I decided to take a look at the implementation of Math.Pow() function. But in .NET Reflector, all I found was this:
[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public static extern double Pow(double x, double y);
What are some of the resources wherein I can see as what's going on inside when I call Math.Pow() function?
MethodImplOptions.InternalCall
That means that the method is actually implemented in the CLR, written in C++. The just-in-time compiler consults a table with internally implemented methods and compiles the call to the C++ function directly.
Having a look at the code requires the source code for the CLR. You can get that from the SSCLI20 distribution. It was written around the .NET 2.0 time frame, I've found the low-level implementations, like Math.Pow() to be still largely accurate for later versions of the CLR.
The lookup table is located in clr/src/vm/ecall.cpp. The section that's relevant to Math.Pow() looks like this:
FCFuncStart(gMathFuncs)
FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin)
FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs)
FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs)
FCFuncElement("Exp", COMDouble::Exp)
FCFuncElement("Pow", COMDouble::Pow)
// etc..
FCFuncEnd()
Searching for "COMDouble" takes you to clr/src/classlibnative/float/comfloat.cpp. I'll spare you the code, just have a look for yourself. It basically checks for corner cases, then calls the CRT's version of pow().
The only other implementation detail that's interesting is the FCIntrinsic macro in the table. That's a hint that the jitter may implement the function as an intrinsic. In other words, substitute the function call with a floating point machine code instruction. Which is not the case for Pow(), there is no FPU instruction for it. But certainly for the other simple operations. Notable is that this can make floating point math in C# substantially faster than the same code in C++, check this answer for the reason why.
By the way, the source code for the CRT is also available if you have the full version of Visual Studio vc/crt/src directory. You'll hit the wall on pow() though, Microsoft purchased that code from Intel. Doing a better job than the Intel engineers is unlikely. Although my high-school book's identity was twice as fast when I tried it:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
But not a true substitute because it accumulates error from 3 floating point operations and doesn't deal with the weirdo domain problems that Pow() has. Like 0^0 and -Infinity raised to any power.
Hans Passant's answer is great, but I would like to add that if b is an integer, then a^b can be computed very efficiently with binary decomposition. Here's a modified version from Henry Warren's Hacker's Delight:
public static int iexp(int a, uint b) {
int y = 1;
while(true) {
if ((b & 1) != 0) y = a*y;
b = b >> 1;
if (b == 0) return y;
a *= a;
}
}
He notes that this operation is optimal (does the minimum number of arithmetic or logical operations) for all b < 15. Also there is no known solution to the general problem of finding an optimal sequence of factors to compute a^b for any b other than an extensive search. It's an NP-Hard problem. So basically that means that the binary decomposition is as good as it gets.
If freely available C version of pow is any indication, it does not look like anything you would expect. It would not be of much help to you to find the .NET version, because the problem that you are solving (i.e. the one with integers) is orders of magnitudes simpler, and can be solved in a few lines of C# code with the exponentiation by squaring algorithm.
Going through the answers, learned a lot about behind-the-scene calculations:
I've tried some workarounds on a coding platform which has an extensive test coverage cases, and found a very effective way doing it(Solution 3):
public double MyPow(double x, int n) {
double res = 1;
/* Solution 1: iterative : TLE(Time Limit Exceeded)
double res = 1;
var len = n > 0 ? n : -n;
for(var i = 0; i < len; ++i)
res *= x;
return n > 0 ? res : 1 / res;
*/
/* Solution 2: recursive => stackoverflow exception
if(x == 0) return n > 0 ? 0 : 1 / x;
if(n == 1) return x;
return n > 0 ? x * MyPow(x, n - 1) : (1/x) * MyPow(1/x, -n);
*/
//Solution 3:
if (n == 0) return 1;
var half = MyPow(x, n / 2);
if (n % 2 == 0)
return half * half;
else if (n > 0)
return half * half * x;
else
return half * half / x;
/* Solution 4: bitwise=> TLE(Time Limit Exceeded)
var b = n > 0 ? n : -n;
while(true) {
if ((b & 1) != 0)
res *= x;
b = b >> 1;
if (b == 0) break;
x *= x;
}
return n > 0 ? res : 1 / res;
*/
}
Answer that is accepted on Leetcode:
public class Solution {
public double MyPow(double x, int n) {
if(n==0) return 1;
long abs = Math.Abs((long)n);
var result = pow(x, abs);
return n > 0 ? result : 1/result;
}
double pow(double x, long n){
if(n == 1) return x;
var result = pow(x, n/2);
result = result * result * (n%2 == 1? x : 1);
return result;
}
}