If possible, I'd like a function f(i,j)=k defined as follows

  • Thread starter Jamin2112
  • Start date
  • Tags
    Function
In summary, the conversation discusses different ways to simplify a code with multiple if/else statements. Various mathematical functions are suggested, including a polynomial, a linear combination, and a division operation. However, it is also noted that simplifying the code in this way may not be the most efficient or readable approach. Ultimately, it is recommended to stick with a straightforward algorithm for better understanding and maintainability in programming.
  • #1
Jamin2112
986
12
I'm writing a piece of code and I want to simplify a bunch of if/else statements.

I need f:{-1,1}x{-1,1}-->{1,2,3,4} with

f(1,-1)=1
f(1,1)=2
f(-1,1)=3
f(-1,-1)=4


Can anyone think of a mathematical function that will give me the desired output?
 
Mathematics news on Phys.org
  • #2
In other words, I want a fancy way of simplifying

Code:
     if (dx == 1 && dy == -1)
        th = 1;
     else if (dx == 1 && dy == 1)
        th = 2;
     else if (dx == -1 && dy == 1)
        th = 3;
     else // (dx == -1 && dy == -1)
        th == 4;

I want to write 1 line:

Code:
th = ? // some operation(s) on dx and dy
 
  • #3
I haven't given much though to a math function to do this, but you could simplify your if block like so:
Code:
if (dx == 1)
{
   th = (int)(1.5 + 0.5 * dy);
}
else if (dx == -1)
{
   th = (int)(3.5  - 0.5 *dy);
}
If there are only the four possible combinations of -1 and 1, the else clause I have above could be further simplified by changing "else if (dx == -1)" to simply "else".
 
Last edited:
  • #4
I just did some curve fitting in Excel and got this;

=-(1/6)*(dx+2*dy)^3+(1/8)*(dx+2*dy)^2+(7/6)*(dx+2*dy)+(15/8)

In Excel that rounds to the exact numbers you need. If that doesn't round correctly for you, you can do a higher order fit.

Probably not the "best" function, but its "a" function. :)
 
  • #5
How about
$$f(x,y) = -x + \frac{5 + xy}{2}$$
Solved by presuming a form ##f(x,y) = ax + by + c + dxy##, which gives us the following 4x4 linear equation
$$\begin{bmatrix} 1 & -1 & 1 & -1 \\
1 & 1 & 1 & 1 \\
-1 & 1 & 1 & -1 \\
-1 & -1 & 1 & 1\\
\end{bmatrix} \begin{bmatrix} a \\ b \\ c \\ d \\ \end{bmatrix} = \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ \end{bmatrix}$$
I let Matlab do the dirty work, which gave me ##a=-1, b = 0, c = 5/2, d = 1/2##.
 
Last edited:
  • #6
Did you know there could be a solution of that form before letting Matlab do the dirty work?
 
  • #7
At first I thought there would be a solution of the form ##ax + by + c##: first linearly map the values of ##x## into 0 and 1, and the same with ##y##, then map the resulting pair into the values 0, 1, 2, 3 (binary representation with two "bits"), then add one. It would have worked if he had wanted

f(1,-1)=1
f(1,1)=2
f(-1,-1)=3
f(-1,1)=4

but his map reverses the 3 and 4. If this had worked, the problem would have had 4 equations and 3 unknowns, but the 4th equation would be a linear combination of the first 3, hence consistent Since it didn't work, I needed a 4th unknown, thus one more term involving ##x## and ##y##. Instead of ##dxy## you can use ##d## times just about any function ##g(x,y)## as long as the 4th column of the matrix is linearly independent of the first three. But ##xy## has the advantage of being easy to calculate for ##x,y = \pm 1##. :biggrin:
 
  • Like
Likes 1 person
  • #8
P.S. As it happens, we only needed 3 unknowns, namely ##a,c,d##, since ##b## ended up being zero. So I could have used the form ##ax + c + dxy##. But I didn't know that until after the fact.
 
  • #9
Simplifying code to a math function is probably not a great idea, in this particular case, although it is really interesting.

Mark's simplification is still readable.

Something to solve jbunnii's function would not be inherently enlightening nor would it be "self documenting" the way Mark's code is.

And the machine code for if/else is really elementary and fast. jbunnii's function is actually quite cool, but it involves 2 additions, a negation, a multiplication and a division. So if this has to be fast it may be possible the division could slow you down. Depends on your platform and compiler.

My comment about performance was posted without seeing jbunnii's last post. Oops.

FWIW, if you don't care about overhead, create an associative array, then statically assign results {1...4} to each element:
Code:
th = assoc_arr[ to_string(dx, dy)];
. This is more than bit much, but the result is just as elegant as the math function approach.

If you have many if then else checks, consider changing to a switch() construct. Function pointer arrays are great for simplifying multiple branches into functions that take identical datatypes.
http://www.newty.de/fpt/fpt.html#arrays
 
  • #10
Agree fully with jim mcnamara that you should NOT implement it this way in software if you care about efficiency and, much more importantly, readability/maintainability. In my day job as a software engineer, if I were to encounter a smartass function like this in our source code, I would want to strangle whoever wrote it. But it would be an interesting interview question. :tongue:

Much better to write something like your original code:
Code:
     if (dx == 1 && dy == -1)
        th = 1;
     else if (dx == 1 && dy == 1)
        th = 2;
     else if (dx == -1 && dy == 1)
        th = 3;
     else // (dx == -1 && dy == -1)
        th == 4;
[edit] removed alternate code which calculated the wrong answer
 
  • #11
jbunni, I agree. I don't see any problem with the if ... else block as shown in post #2. "Clever" code is seldom the best way to go, and a straightforward algorithm is to be preferred, not least for the sake of being more understandable to the maintenance programmer.
 
  • #12
Good answers, guys. Thanks!
 
  • #13
x= 1+(1-i)+(j*i+1)/2 works.
But I agree that simpler is better in programming.
You can use the if/then or define a doubly-dimensioned array to look up the correct value.
 
  • #14
If you want speed, just use a lookup table.
Code:
static const int fdata[2][2] = {{4,0,3},{0,0,0},{(1,0,2}};

int f(int x, int y)
{
    return fdata[x+1][y+1];
}
 
  • #15
AlephZero said:
If you want speed, just use a lookup table.
Code:
static const int fdata[2][2] = {{4,0,3},{0,0,0},{(1,0,2}};

int f(int x, int y)
{
    return fdata[x+1][y+1];
}
The fdata array has too many elements in it. You're probably thinking that the array is 3 X 3, and that the indexes run 0, 1, 2. There is also an extra left paren in the last group of three numbers.
 
  • #16
Mark44 said:
You're probably thinking that the array is 3 X 3, and that the indexes run 0, 1, 2.

True. I mostly use languages that support arrays properly (unlike C and C++), so the dimensions would run from -1 to 1 and you would just return fdata(i.j).
 
  • #17
AlephZero said:
True. I mostly use languages that support arrays properly (unlike C and C++), so the dimensions would run from -1 to 1 and you would just return fdata(i.j).
Unless you're referring to Fortran, then whatever languages you're talking about are newer than C, which has been around since the early 70's. Newer languages don't have the need to maintain compatability with existing code, so can start on a clean page. For me, it's not a hardship to forgo negative array subscripts.
 
  • #18
As a side note, I will point out that it is possible to use negative indices in C and C++. For example, I can write

Code:
int data[] = {1, 2, 3};
int *pData = &data[1];
Then I can access the elements of the array using either data[0],data[1],data[2] or pData[-1],pData[0],pData[1].

For two-dimensional arrays it can still be done, but setting it up is uglier.

Code:
int data[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
int *pData[3] = {&data[0][1], &data[1][1], &data[2][1]};
int **ppData = &pData[1];
This allows me to write ppData[n-1][m-1] instead of data[m][n], where ##0 \leq m,n \leq 2##.

It's usually too hideous to contemplate doing this sort of thing in code for public consumption, but if you encapsulate the ugly implementation in a class, the ability to use negative subscripts can sometimes make the code that uses the array clearer, e.g. if the 2d array represents a kernel being used in an image processing operation.
 
  • #19
The original solution by Mark44 is a simple, direct solution. (The dimensions were off and a typo, but without a compiler it is hard to get it right the first time.) Regarding array indices and table look-ups, nothing can beat the versatility of well implemented associative arrays (aka hash tables, dictionaries, etc.). C++ hash tables (unordered_map) are awkward to use, Perl is very good, Python looks good but I have no experience with it.
 
  • #20
FactChecker said:
The original solution by Mark44 is a simple, direct solution. (The dimensions were off and a typo, but without a compiler it is hard to get it right the first time.)
I'm not sure what you're talking about. I didn't use arrays at all. You might be referring to the code that AlephZero wrote that I quoted in one post.
FactChecker said:
Regarding array indices and table look-ups, nothing can beat the versatility of well implemented associative arrays (aka hash tables, dictionaries, etc.). C++ hash tables (unordered_map) are awkward to use, Perl is very good, Python looks good but I have no experience with it.
 
  • #21
Mark44 said:
Unless you're referring to Fortran, then whatever languages you're talking about are newer than C, which has been around since the early 70's. Newer languages don't have the need to maintain compatability with existing code, so can start on a clean page. For me, it's not a hardship to forgo negative array subscripts.

IIRC, PL/1 (which I used back in the days of IBM S/360 mainframes) had this feature before Fortran.

C's model of arrays (like almost everything else in C) is tied much too closely to the "standard" computer hardware designs when it was invented. But at least the same people didn't make the same mistake twice when they invented Unix.
 
  • #22
Mark44 said:
I'm not sure what you're talking about. I didn't use arrays at all. You might be referring to the code that AlephZero wrote that I quoted in one post.

Sorry. You're right. It was AlephZero.
 

1. What is a function?

A function is a mathematical concept that relates an input value (or values) to an output value. In other words, it describes a relationship between two or more variables. In this case, the function f(i,j)=k takes in two inputs, i and j, and produces an output, k.

2. What does the notation "f(i,j)=k" mean?

The notation "f(i,j)=k" denotes a function named f that takes in two inputs, i and j, and produces an output, k. The letters i and j are known as the independent variables, while k is the dependent variable.

3. How is a function typically defined?

A function is typically defined by a set of rules or equations that specify how the input values are related to the output values. In other words, the function describes how to transform the independent variables into the dependent variable.

4. What does "If possible" mean in this context?

In this context, "if possible" means that there may be limitations or constraints that prevent the function from being defined for all possible values of i and j. It is important to consider these limitations when defining the function to ensure that it is valid and accurate.

5. What are some potential applications of this function?

This function could have many potential applications in various fields, such as mathematics, physics, engineering, and computer science. It could be used to model complex systems, solve equations, or analyze data, among other things. The specific application would depend on the context in which the function is being used.

Similar threads

Replies
1
Views
1K
  • Programming and Computer Science
Replies
31
Views
2K
Replies
4
Views
385
Replies
1
Views
1K
  • General Math
Replies
23
Views
1K
Replies
6
Views
1K
Replies
1
Views
947
  • Topology and Analysis
2
Replies
38
Views
3K
Replies
5
Views
1K
  • Calculus and Beyond Homework Help
Replies
3
Views
264
Back
Top