I'd like to be able to swap two variables without the use of a temporary variable in C#. Can this be done?
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
// Swap each:
// startAngle becomes: 355.87
// stopAngle becomes: 159.9
C# 7 introduced tuples which enables swapping two variables without a temporary one:
int a = 10;
int b = 2;
(a, b) = (b, a);
This assigns b to a and a to b.
The right way to swap two variables (at the time this question was asked(1)) is:
decimal tempDecimal = startAngle;
startAngle = stopAngle;
stopAngle = tempDecimal;
In other words, use a temporary variable.
There you have it. No clever tricks, no maintainers of your code cursing you for decades to come, no entries to The Daily WTF, and no spending too much time trying to figure out why you needed it in one operation anyway since, at the lowest level, even the most complicated language feature is a series of simple operations.
Just a very simple, readable, easy to understand, t = a; a = b; b = t; solution.
In my opinion, developers who try to use tricks to, for example, "swap variables without using a temp" or "Duff's device" are just trying to show how clever they are (and failing miserably).
I liken them to those who read highbrow books solely for the purpose of seeming more interesting at parties (as opposed to expanding your horizons).
Solutions where you add and subtract, or the XOR-based ones, are less readable and most likely slower than a simple "temp variable" solution (arithmetic/boolean-ops instead of plain moves at an assembly level).
Do yourself, and others, a service by writing good quality readable code.
That's my rant. Thanks for listening :-)
As an aside, I'm quite aware this doesn't answer your specific question (and I'll apologise for that) but there's plenty of precedent on SO where people have asked how to do something and the correct answer is "Don't do it".
(1) Improvements to the language and/or .NET Core since that time have adopted the "Pythonic" way using tuples. Now you can just do:
(startAngle, stopAngle) = (stopAngle, startAngle);
to swap values.
First of all, swapping without a temporary variable in a language as C# is a very bad idea.
But for the sake of answer, you can use this code:
startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;
Problems can however occur with rounding off if the two numbers differ largely. This is due to the nature of floating point numbers.
If you want to hide the temporary variable, you can use a utility method:
public static class Foo {
public static void Swap<T> (ref T lhs, ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
}
Yes, use this code:
stopAngle = Convert.ToDecimal(159.9);
startAngle = Convert.ToDecimal(355.87);
The problem is harder for arbitrary values. :-)
int a = 4, b = 6;
a ^= b ^= a ^= b;
Works for all types including strings and floats.
BenAlabaster showed a practical way of doing a variable switch, but the try-catch clause is not needed. This code is enough.
static void Swap<T>(ref T x, ref T y)
{
T t = y;
y = x;
x = t;
}
The usage is the same as he shown:
float startAngle = 159.9F
float stopAngle = 355.87F
Swap(ref startAngle, ref stopAngle);
You could also use an extension method:
static class SwapExtension
{
public static T Swap<T>(this T x, ref T y)
{
T t = y;
y = x;
return t;
}
}
Use it like this:
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle.Swap(ref stopAngle);
Both ways uses a temporary variable in the method, but you don't need the temporary variable where you do the swapping.
A binary XOR swap with a detailed example:
XOR truth table:
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
Input:
a = 4;
b = 6;
Step 1: a = a ^ b
a : 0100
b : 0110
a^b: 0010 = 2 = a
Step 2: b = a ^ b
a : 0010
b : 0110
a^b: 0100 = 4 = b
Step 3: a = a ^ b
a : 0010
b : 0100
a^b: 0110 = 6 = a
Output:
a = 6;
b = 4;
In C# 7:
(startAngle, stopAngle) = (stopAngle, startAngle);
Not in C#. In native code you might be able to use the triple-XOR swap trick, but not in a high level type-safe language. (Anyway, I've heard that the XOR trick actually ends up being slower than using a temporary variable in many common CPU architectures.)
You should just use a temporary variable. There's no reason you can't use one; it's not like there's a limited supply.
For the sake of future learners, and humanity, I submit this correction to the currently selected answer.
If you want to avoid using temp variables, there are only two sensible options that take first performance and then readability into consideration.
Use a temp variable in a generic Swap method. (Absolute best performance, next to inline temp variable)
Use Interlocked.Exchange. (5.9 times slower on my machine, but this is your only option if multiple threads will be swapping these variables simultaneously.)
Things you should never do:
Never use floating point arithmetic. (slow, rounding and overflow errors, hard to understand)
Never use non-primitive arithmetic. (slow, overflow errors, hard to understand) Decimal is not a CPU primitive and results in far more code than you realize.
Never use arithmetic period. Or bit hacks. (slow, hard to understand) That's the compiler's job. It can optimize for many different platforms.
Because everyone loves hard numbers, here's a program that compares your options. Run it in release mode from outside Visual Studio so that Swap is inlined. Results on my machine (Windows 7 64-bit i5-3470):
Inline: 00:00:00.7351931
Call: 00:00:00.7483503
Interlocked: 00:00:04.4076651
Code:
class Program
{
static void Swap<T>(ref T obj1, ref T obj2)
{
var temp = obj1;
obj1 = obj2;
obj2 = temp;
}
static void Main(string[] args)
{
var a = new object();
var b = new object();
var s = new Stopwatch();
Swap(ref a, ref b); // JIT the swap method outside the stopwatch
s.Restart();
for (var i = 0; i < 500000000; i++)
{
var temp = a;
a = b;
b = temp;
}
s.Stop();
Console.WriteLine("Inline temp: " + s.Elapsed);
s.Restart();
for (var i = 0; i < 500000000; i++)
{
Swap(ref a, ref b);
}
s.Stop();
Console.WriteLine("Call: " + s.Elapsed);
s.Restart();
for (var i = 0; i < 500000000; i++)
{
b = Interlocked.Exchange(ref a, b);
}
s.Stop();
Console.WriteLine("Interlocked: " + s.Elapsed);
Console.ReadKey();
}
}
<deprecated>
You can do it in 3 lines using basic math - in my example I used multiplication, but simple addition would work also.
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;
Edit: As noted in the comments, this wouldn't work if y = 0 as it would generate a divide by zero error which I hadn't considered. So the +/- solution alternatively presented would be the best way to go.
</deprecated>
To keep my code immediately comprehensible, I'd be more likely to do something like this. [Always think about the poor guy that's gonna have to maintain your code]:
static bool Swap<T>(ref T x, ref T y)
{
try
{
T t = y;
y = x;
x = t;
return true;
}
catch
{
return false;
}
}
And then you can do it in one line of code:
float startAngle = 159.9F
float stopAngle = 355.87F
Swap<float>(ref startAngle, ref stopAngle);
Or...
MyObject obj1 = new MyObject("object1");
MyObject obj2 = new MyObject("object2");
Swap<MyObject>(ref obj1, ref obj2);
Done like dinner...you can now pass in any type of object and switch them around...
With C# 7, you can use tuple deconstruction to achieve the desired swap in one line, and it's clear what's going on.
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(startAngle, stopAngle) = (stopAngle, startAngle);
For completeness, here is the binary XOR swap:
int x = 42;
int y = 51236;
x ^= y;
y ^= x;
x ^= y;
This works for all atomic objects/references, as it deals directly with the bytes, but may require an unsafe context to work on decimals or, if you're feeling really twisted, pointers. And it may be slower than a temp variable in some circumstances as well.
If you can change from using decimal to double you can use the Interlocked class.
Presumably this will be a good way of swapping variables performance wise. Also slightly more readable than XOR.
var startAngle = 159.9d;
var stopAngle = 355.87d;
stopAngle = Interlocked.Exchange(ref startAngle, stopAngle);
Msdn: Interlocked.Exchange Method (Double, Double)
a = a + b
b = a - b
a = a - b
َ
Beware of your environment!
For example, this doesn’t seem to work in ECMAscript
y ^= x ^= y ^= x;
But this does
x ^= y ^= x; y ^= x;
My advise? Assume as little as possible.
The simple way to swap 2 numbers in just one line:
a=(a+b)-(b=a);
eg: a=1, b=2
Step 1: a=(1+2) - (b=1)
Step 2: a=3-1
=> a=2 and b=1
Efficient way is to use:
C Programming: (x ^= y), (y ^= x), (x ^= y);
Java: x = x ^ y ^ (y = x);
Python: x, y = y, x
Note: Most common mistake people make:
//Swap using bitwise XOR (Wrong Solution in C/C++)
x ^= y ^= x ^= y;
Source: GeeksforGeek
For binary types you can use this funky trick:
a %= b %= a %= b;
As long as a and b are not the exact same variable (e.g. aliases for the same memory) it works.
I hope this might help...
using System;
public class Program
{
public static void Main()
{
int a = 1234;
int b = 4321;
Console.WriteLine("Before: a {0} and b {1}", a, b);
b = b - a;
a = a + b;
b = a - b;
Console.WriteLine("After: a {0} and b {1}", a, b);
}
}
we can do that by doing a simple trick
a = 20;
b = 30;
a = a+b; // add both the number now a has value 50
b = a-b; // here we are extracting one number from the sum by sub
a = a-b; // the number so obtained in above help us to fetch the alternate number from sum
System.out.print("swapped numbers are a = "+ a+"b = "+ b);
Sometimes I wish it were possible to write a function in MSIL inline in C#, similar to how you can write inline assembler in C.
For the record, I once wrote a helper library for C# with various functions for things that were impossible to write in C# but can be written in MSIL (non-zero-based arrays for example). I had this function:
.method public hidebysig static void Swap<T> (
!!T& a,
!!T& b
) cil managed
{
.maxstack 4
ldarg.1 // push a& reference
ldarg.2 // push b& reference
ldobj !!T // pop b&, push b
ldarg.2 // push b& reference
ldarg.1 // push a& reference
ldobj !!T // pop a&, push a
stobj !!T // store a in b&
stobj !!T // store b in a&
ret
}
And no locals needed. Of course this was just me being silly...
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
If you want to swap 2 string variables:
a = (a+b).Substring((b=a).Length);
An helper method accordingly:
public static class Foo {
public static void SwapString (ref string a, ref string b) {
a = (a+b).Substring((b=a).Length);
}
}
Usage would be then:
string a="Test 1";
string b="Test 2";
Foo.SwapString(a, b);
Here another approach in one line:
decimal a = 159.9m;
decimal b = 355.87m;
a = b + (b = a) - b;
Here is some different process to swap two variables
//process one
a=b+a;
b=a-b;
a=a-b;
printf("a= %d b= %d",a,b);
//process two
a=5;
b=10;
a=a+b-(b=a);
printf("\na= %d b= %d",a,b);
//process three
a=5;
b=10;
a=a^b;
b=a^b;
a=b^a;
printf("\na= %d b= %d",a,b);
//process four
a=5;
b=10;
a=b-~a-1;
b=a+~b+1;
a=a+~b+1;
printf("\na= %d b= %d",a,b);
this model is very useful
var a = 10;
var b = 20;
(int a,int b) c = (a,b);
a = c.b ;
b = c.a ;
var a = 15;
var b = -214;
a = b | !(b = a);
This works great.
Very simple code for swapping two variables:
static void Main(string[] args)
{
Console.WriteLine("Prof.Owais ahmed");
Console.WriteLine("Swapping two variables");
Console.WriteLine("Enter your first number ");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter your first number ");
int y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("your vlaue of x is="+x+"\nyour value of y is="+y);
int z = x;
x = y;
y = z;
Console.WriteLine("after Swapping value of x is="+x+"/nyour value of y is="+y);
Console.ReadLine();
}
You can try the following code. It is much more better than the other code.
a = a + b;
b = a - b;
a = a - b;
Related
I have been converting a Python script to C#, I am 99% there but I am having trouble understanding the following piece of code
# The lower 8-bits from the Xorshift PNR are subtracted from byte
# values during extraction, and added to byte values on insertion.
# When calling deobfuscate_string() the whole string is processed.
def deobfuscate_string(pnr, obfuscated, operation=int.__sub__):
return ''.join([chr((ord(c) operation pnr.next()) & 0xff) for c in obfuscated])
Could you please explain the code above? what does operation pnr.next() do? If you could help maybe convert this method to C# that would be even better but an explanation of the above would be great.
Full source can be found at
https://raw.githubusercontent.com/sladen/pat/master/gar.py
The snippet you provided is not a valid Python code. One cannot write a function name in the place of an infix operator. I think it is meant to be like this:
# The lower 8-bits from the Xorshift PNR are subtracted from byte
# values during extraction, and added to byte values on insertion.
# When calling deobfuscate_string() the whole string is processed.
def deobfuscate_string(pnr, obfuscated, operation=int.__sub__):
return ''.join([chr(operation(ord(c), pnr.next()) & 0xff) for c in obfuscated])
You see, this way it will execute the the operation on ord(c) and pnr.next(). This way the translation to C# is straightforward, operation should be of type Func<int, int, int>.
This might give you an idea:
public static T Next<T>(IEnumerator<T> en) {
en.MoveNext();
return en.Current;
}
public static string deobfuscate_string(IEnumerator<int> pnr, string obfuscated, Func<int, int, int> operation = null) {
if (operation == null) operation = (a, b) => a - b;
return string.Join("", from c in obfuscated select (char)operation((int)c, Next(pnr)));
}
EDIT: added default parameter to deobfuscate_string
The function deobfuscate_string takes an iterable pnr, a string obfuscated and an operation that is by default substract.
For each character c in the string obfuscated
It apply the
operator (substract by default) to the value of the character with
the next element in pnr.
Then it uses & 0xff to ensure result is in range 255
Every thing is then combine in a string.
So, it just encrypt the input by rotating every characters from a known set of rotations.
Notice: The code is not valid as operation cannot by used this way, I just explain the goal here.
Thank you everyone for posting responses, I ended up grabbing a Python debugger and working it through.
private static byte[] deobfuscate_string(XORShift128 pnr, byte[] obfuscated)
{
byte[] deobfuscated = new byte[obfuscated.Length];
for (int i = 0; i < obfuscated.Length; i++)
{
byte b = Convert.ToByte((obfuscated[i] - pnr.next()) & 0xff);
deobfuscated[i] = b;
}
Array.Reverse(deobfuscated);
return deobfuscated;
}
private class XORShift128
{
private UInt32 x = 123456789;
private UInt32 y = 362436069;
private UInt32 z = 521288629;
private UInt32 w = 88675123;
public XORShift128(UInt32 x, UInt32 y)
{
this.x = x;
this.y = y;
}
public UInt32 next()
{
UInt32 t = (x ^ (x << 11)) & 0xffffffff;
x = y;
y = z;
z = w;
w = (w ^ (w >> 19) ^ (t ^ (t >> 8)));
return w;
}
}
Above is that I ended up with
To clarify first:
2^3 = 8. That's equivalent to 2*2*2. Easy.
2^4 = 16. That's equivalent to 2*2*2*2. Also easy.
2^3.5 = 11.313708... Er, that's not so easy to grok.
Want I want is a simple algorithm which most clearly shows how 2^3.5 = 11.313708. It should preferably not use any functions apart from the basic addition, subtract, multiply, or divide operators.
The code certainly doesn't have to be fast, nor does it necessarily need to be short (though that would help). Don't worry, it can be approximate to a given user-specified accuracy (which should also be part of the algorithm). I'm hoping there will be a binary chop/search type thing going on, as that's pretty simple to grok.
So far I've found this, but the top answer is far from simple to understand on a conceptual level.
The more answers the merrier, so I can try to understand different ways of attacking the problem.
My language preference for the answer would be C#/C/C++/Java, or pseudocode for all I care.
Ok, let's implement pow(x, y) using only binary searches, addition and multiplication.
Driving y below 1
First, take this out of the way:
pow(x, y) == pow(x*x, y/2)
pow(x, y) == 1/pow(x, -y)
This is important to handle negative exponents and drive y below 1, where things start getting interesting. This reduces the problem to finding pow(x, y) where 0<y<1.
Implementing sqrt
In this answer I assume you know how to perform sqrt. I know sqrt(x) = x^(1/2), but it is easy to implement it just using a binary search to find y = sqrt(x) using y*y=x search function, e.g.:
#define EPS 1e-8
double sqrt2(double x) {
double a = 0, b = x>1 ? x : 1;
while(abs(a-b) > EPS) {
double y = (a+b)/2;
if (y*y > x) b = y; else a = y;
}
return a;
}
Finding the answer
The rationale is that every number below 1 can be approximated as a sum of fractions 1/2^x:
0.875 = 1/2 + 1/4 + 1/8
0.333333... = 1/4 + 1/16 + 1/64 + 1/256 + ...
If you find those fractions, you actually find that:
x^0.875 = x^(1/2+1/4+1/8) = x^(1/2) * x^(1/4) * x^(1/8)
That ultimately leads to
sqrt(x) * sqrt(sqrt(x)) * sqrt(sqrt(sqrt(x)))
So, implementation (in C++)
#define EPS 1e-8
double pow2(double x, double y){
if (x < 0 and abs(round(y)-y) < EPS) {
return pow2(-x, y) * ((int)round(y)%2==1 ? -1 : 1);
} else if (y < 0) {
return 1/pow2(x, -y);
} else if(y > 1) {
return pow2(x * x, y / 2);
} else {
double fraction = 1;
double result = 1;
while(y > EPS) {
if (y >= fraction) {
y -= fraction;
result *= x;
}
fraction /= 2;
x = sqrt2(x);
}
return result;
}
}
Deriving ideas from the other excellent posts, I came up with my own implementation. The answer is based on the idea that base^(exponent*accuracy) = answer^accuracy. Given that we know the base, exponent and accuracy variables beforehand, we can perform a search (binary chop or whatever) so that the equation can be balanced by finding answer. We want the exponent in both sides of the equation to be an integer (otherwise we're back to square one), so we can make accuracy any size we like, and then round it to the nearest integer afterwards.
I've given two ways of doing it. The first is very slow, and will often produce extremely high numbers which won't work with most languages. On the other hand, it doesn't use log, and is simpler conceptually.
public double powSimple(double a, double b)
{
int accuracy = 10;
bool negExponent = b < 0;
b = Math.Abs(b);
bool ansMoreThanA = (a>1 && b>1) || (a<1 && b<1); // Example 0.5^2=0.25 so answer is lower than A.
double accuracy2 = 1.0 + 1.0 / accuracy;
double total = a;
for (int i = 1; i < accuracy* b; i++) total = total*a;
double t = a;
while (true) {
double t2 = t;
for(int i = 1; i < accuracy; i++) t2 = t2 * t; // Not even a binary search. We just hunt forwards by a certain increment
if((ansMoreThanA && t2 > total) || (!ansMoreThanA && t2 < total)) break;
if (ansMoreThanA) t *= accuracy2; else t /= accuracy2;
}
if (negExponent) t = 1 / t;
return t;
}
This one below is a little more involved as it uses log(). But it is much quicker and doesn't suffer from the super-high number problems as above.
public double powSimple2(double a, double b)
{
int accuracy = 1000000;
bool negExponent= b<0;
b = Math.Abs(b);
double accuracy2 = 1.0 + 1.0 / accuracy;
bool ansMoreThanA = (a>1 && b>1) || (a<1 && b<1); // Example 0.5^2=0.25 so answer is lower than A.
double total = Math.Log(a) * accuracy * b;
double t = a;
while (true) {
double t2 = Math.Log(t) * accuracy;
if ((ansMoreThanA && t2 > total) || (!ansMoreThanA && t2 < total)) break;
if (ansMoreThanA) t *= accuracy2; else t /= accuracy2;
}
if (negExponent) t = 1 / t;
return t;
}
You can verify that 2^3.5 = 11.313708 very easily: check that 11.313708^2 = (2^3.5)^2 = 2^7 = 128
I think the easiest way to understand the computation you would actually do for this would be to refresh your understanding of logarithms - one starting point would be http://en.wikipedia.org/wiki/Logarithm#Exponentiation.
If you really want to compute non-integer powers with minimal technology one way to do that would be to express them as fractions with denominator a power of two and then take lots of square roots. E.g. x^3.75 = x^3 * x^(1/2) * x^(1/4) then x^(1/2) = sqrt(x), x^(1/4) = sqrt(sqrt(x)) and so on.
Here is another approach, based on the idea of verifying a guess. Given y, you want to find x such that x^(a/b) = y, where a and b are integers. This equation implies that x^a = y^b. You can calculate y^b, since you know both numbers. You know a, so you can - as you originally suspected - use binary chop or perhaps some numerically more efficient algorithm to solve x^a = y^b for x by simply guessing x, computing x^a for this guess, comparing it with y^b, and then iteratively improving the guess.
Example: suppose we wish to find 2^0.878 by this method. Then set a = 439, b = 500, so we wish to find 2^(439/500). If we set x=2^(439/500) we have x^500 = 2^439, so compute 2^439 and (by binary chop or otherwise) find x such that x^500 = 2^439.
Most of it comes down to being able to invert the power operation.
In other words, the basic idea is that (for example) N2 should be basically the "opposite" of N1/2 so that if you do something like:
M = N2
L = M1/2
Then the result you get in L should be the same as the original value in N (ignoring any rounding and such).
Mathematically, that means that N1/2 is the same as sqrt(N), N1/3 is the cube root of N, and so on.
The next step after that would be something like N3/2. This is pretty much the same idea: the denominator is a root, and the numerator is a power, so N3/2 is the square root of the cube of N (or the cube of the square root of N--works out the same).
With decimals, we're just expressing a fraction in a slightly different form, so something like N3.14 can be viewed as N314/100--the hundredth root of N raised to the power 314.
As far as how you compute these: there are quite a few different ways, depending heavily on the compromise you prefer between complexity (chip area, if you're implementing it in hardware) and speed. The obvious way is to use a logarithm: AB = Log-1(Log(A)*B).
For a more restricted set of inputs, such as just finding the square root of N, you can often do better than that extremely general method though. For example, the binary reducing method is quite fast--implemented in software, it's still about the same speed as Intel's FSQRT instruction.
As stated in the comments, its not clear if you want a mathematical description of how fractional powers work, or an algorithm to calculate fractional powers.
I will assume the latter.
For almost all functions (like y = 2^x) there is a means of approximating the function using a thing called the Taylor Series http://en.wikipedia.org/wiki/Taylor_series. This approximates any reasonably behaved function as a polynomial, and polynomials can be calculated using only multiplication, division, addition and subtraction (all of which the CPU can do directly). If you calculate the Taylor series for y = 2^x and plug in x = 3.5 you will get 11.313...
This almost certainly not how exponentiation is actually done on your computer. There are many algorithms which run faster for different inputs. For example, if you calculate 2^3.5 using the Taylor series, then you would have to look at many terms to calculate it with any accuracy. However, the Taylor series will converge much faster for x = 0.5 than for x = 3.5. So one obvious improvement is to calculate 2^3.5 as 2^3 * 2^0.5, as 2^3 is easy to calculate directly. Modern exponentiation algorithms will use many, many tricks to speed up processing - but the principle is still much the same, approximate the exponentiation function as some infinite sum, and calculate as many terms as you need to get the accuracy that is required.
This question already has answers here:
Swap two variables without using a temporary variable
(29 answers)
Closed 8 years ago.
Swap two variables without using a temp variable
if
int a=4;
int b=3;
I need to swap these variable and get output as
a=3 and b=4
without using another variable in C#
Use Interlocked.Exchange()
int a = 4;
int b = 3;
b = Interlocked.Exchange(ref a, b);
Tell me more
From MSDN:
Sets a 32-bit signed integer to a specified value as an atomic operation, and then returns the original value
EDIT: Regarding Esoteric's fine link above (thank-you), there's even a Interlocked.Exchange() for double that may help there too.
use the following concept
int a=4 ;
int b=3 ;
a=a+b ; // a=7
b=a-b ; // b=7-3=4
a=a-b ; // c=7-4=3
There are actually a couple of ways.
The following is considered an obfuscated swap.
a ^= b;
b ^= a;
a ^= b;
a = a + b;
b = a - b;
a = a - b;
Works the same with any language.
Using addition and subtraction
a = a + b;
b = a - b;
a = a - b;
Using xor operator
a = a ^ b;
b = a ^ b;
a = a ^ b;
http://chris-taylor.github.io/blog/2013/02/25/xor-trick/
I have a simple algebraic relationship that uses three variables. I can guarantee that I know two of the three and need to solve for the third, but I don't necessarily know which two of the variables I will know. I'm looking for a single method or algorithm that can handle any of the cases without a huge batch of conditionals. This may not be possible, but I would like to implement it in a more general sense rather than code in every relationship in terms of the other variables.
For example, if this were the relationship:
3x - 5y + z = 5
I don't want to code this:
function(int x, int y)
{
return 5 - 3x + 5y;
}
function(int x, int z)
{
return (5 - z - 3x)/(-5);
}
And so on. Is there a standard sort of way to handle programming problems like this? Maybe using matrices, parameterization, etc?
If you restrict yourself to the kind of linear functions shown above, you could generalize the function like this
3x - 5y + z = 5
would become
a[0]*x[0] + a[1]*x[1] + a[2]*x[2] = c
with a = { 3, -5, 1 } and c = 5.
I.e., you need a list (or array) of constant factors List<double> a; and a list of variables List<double?> x; plus the constant on the right side double c;
public double Solve(IList<double> a, IList<double?> x, double c)
{
int unknowns = 0;
int unkonwnIndex = 0; // Initialization required because the compiler is not smart
// enough to infer that unknownIndex will be initialized when
// our code reaches the return statement.
double sum = 0.0;
if (a.Count != x.Count) {
throw new ArgumentException("a[] and x[] must have same length");
}
for (int i = 0; i < a.Count; i++) {
if (x[i].HasValue) {
sum += a[i] * x[i].Value;
} else {
unknowns++;
unknownIndex = i;
}
}
if (unknowns != 1) {
throw new ArgumentException("Exactly one unknown expected");
}
return (c - sum) / a[unknownIndex];
}
Example:
3x - 5y + z = 5
5 - (- 5y + z)
x = --------------
3
As seen in the example the solution consists of subtracting the sum of all terms except the unknown term from the constant and then to divide by the factor of the unknown. Therefore my solution memorizes the index of the unknown.
You can generalize with powers like this, assuming that you have the equation
a[0]*x[0]^p[0] + a[1]*x[1]^p[1] + a[2]*x[2]^p[2] = c
you need an additional parameter IList<int> p and the result becomes
return Math.Pow((c - sum) / a[unknownIndex], 1.0 / p[unknownIndex]);
as x ^ (1/n) is equal to nth-root(x).
If you use doubles for the powers, you will even be able to represent functions like
5
7*x^3 + --- + 4*sqrt(z) = 11
y^2
a = { 7, 5, 4 }, p = { 3, -2, 0.5 }, c = 11
because
1
x^(-n) = ---
x^n
and
nth-root(x) = x^(1/n)
However, you will not be able to find the roots of true non-linear polynomials like x^2 - 5x = 7. The algorithm shown above, works only, if the unknown appears exactly once in the equation.
Yes, here is one function:
private double? ValueSolved (int? x, int? y, int? z)
{
if (y.HasValue && z.HasValue && !x.HasValue
return (5 + (5 * y.Value) - z.Value) / 3;
if (x.HasValue && z.HasValue && !y.HasValue
return (5 - z.Value - (3 * x.Value)) / -5;
if (x.HasValue && y.HasValue && !z.HasValue
return 5 - (3 * x.Value) + (5 * y.Value);
return null;
}
There is no standard way of solving such a problem.
In the general case, symbolic math is a problem solved by purpose built libraries, Math.NET has a symbolic library you might be interested in: http://symbolics.mathdotnet.com/
Ironically, a much tougher problem, a system of linear equations, can be easily solved by a computer by calculating an inverse matrix. You can set up the provided equation in this manner, but there are no built-in general purpose Matrix classes in .NET.
In your specific case, you could use something like this:
public int SolveForVar(int? x, int? y, int? z)
{
int unknownCount = 0;
int currentSum = 0;
if (x.HasValue)
currentSum += 3 * x.Value;
else
unknownCount++;
if (y.HasValue)
currentSum += -5 * y.Value;
else
unknownCount++;
if (z.HasValue)
currentSum += z.Value;
else
unknownCount++;
if (unknownCount > 1)
throw new ArgumentException("Too Many Unknowns");
return 5 - currentSum;
}
int correctY = SolveForVar(10, null, 3);
Obviously that approach gets unwieldy for large variable counts, and doesn't work if you need lots of dynamic numbers or complex operations, but it could be generalized to a certain extent.
I'm not sure what you are looking for, since the question is tagged symbolic-math but the sample code you have is producing numerical solutions, not symbolic ones.
If you want to find a numerical solution for a more general case, then define a function
f(x, y, z) = 3x - 5y + z - 5
and feed it to a general root-finding algorithm to find the value of the unknown parameter(s) that will produce a root. Most root-finding implementations allow you to lock particular function parameters to fixed values before searching for a root along the unlocked dimensions of the problem.
I am new to C# programming, and I don't know very much of its syntax or how it works, but I've been learning and it's been coming along quite nicely. I'm trying to convert one of my programs I have recently written in Python to C# so it can run on windows without having to install Python. And I've had to change a lot of my methods in converting it, and it's taken a very long time to do, but I've been figuring most things out as I go along. This issue, however, makes absolutely no sense to me. I have assigned a value and a type to the double 'b1' but it's telling me that I can't use it in the definition of b2?
double b;
double b1;
double b2;
if (noSlope == true)
b = 0;
else
b1 = slopem * Convert.ToDouble(x1);
b2 = Convert.ToDouble(y1) - b1;
b = b2;
Visual Studio has been telling me that 'b1' is an unassigned local variable. I thought I just assigned it on the line above? Can anyone tell me why it is doing this, or how to assign a value to b1 so it can be used? Thanks in advance!
In c# blocks are marked using { and }, not indentation. Your current code is equivalent to
double b;
double b1;
double b2;
if (noSlope == true)
{
b = 0;
}
else
{
b1 = slopem * Convert.ToDouble(x1);
}
b2 = Convert.ToDouble(y1) - b1;
b = b2;
As you can see, when the condition is evaluated to true you will not have b1 assigned.
PS. You can rewrite your code to
double b;
if (noSlope == true)
{
b = 0;
}
else
{
b = Convert.ToDouble(y1) - slopem * Convert.ToDouble(x1);
}
or even
double b = noSlope ? 0 : Convert.ToDouble(y1) - slopem * Convert.ToDouble(x1);