Any time there is an "if" I'd say it would either turn into a piecewise function or you'd need some wacky step functions.

Also, please use code tags.

It is possible to convert C++ code to mathematical expressions. And it's basically straightforward. I think your scheme for this is fairly straightforward, except that you seem to write the + operator somehow in ways that don't seem derived from common sense.

If you were to ask for a mathematical expression equivalent to the function, you'd say F(n) = (2*floor(n/2))^(3^floor((n-1)/2)) , but that's not what you want, I'm sure.

Thanks Rashakil Fol , would you mind to explain me how did you find it ?

Thanks Rashakil Fol , would you mind to explain me how did you find it ?

Just by reading the code and looking at what it does.

What about this function

int F( int n , int a, int b )
{
int r=0;
int mid=(a+b)/2;
for( int i=0 ; i<n ; i+=2, mid++)
{
if( i<mid ) r++ ;
if( i<mid && i>a ) r-- ;
if( i==mid ) r=r/2 ;
if( i>mid || i<b ) r=sqrt(r) ;
}
return r ;
}

It might look harder than it is. Here's an explanation of the first one:

Input: n
Start r at 0.
Loop n times (using index from 0 to n-1):
  * when index is less than n/2:
        add 1 to r (this is done n/2 times)
  * when index is equal to n/2:
        mul r by 2 (this is done once)
  * when index is greater than n/2:
        cube r (this is done (n/2)-1 times)

And so the equation is obvious. The second one is the same idea but a little tougher. You need to determine how many times each line executes within the loop.

Thanks

Is this mathematically correct ?

F(n)=I(0,n,n/2) ( does it have the same behavious as the previous function F( real n ) ?)

with

I(r,i,m) =I(r,i-1,m) +R(r,i,m) and I(r,0,m)=R(r,0,m)
R(r,i,m)= R1( r , i , m) + R2( R1( r , i , m) , i , m) + R3( R2( R1( r , i , m) , i , m) , i , m)
R1(r, i , n) = r + ( ifl( i , m) * 1 )
R2( r , i , n ) = ( r * ife( i , m) ) + ( not(ife( i , m) * r )
R3( r , i, n) = ( (r^2) * ifg( i , m) ) + ( not(ifg( i , m) * r )
-----------
isz (x) = floor( 1 / (abs(x) +1) )
Out : 1 if x=0 , 0 if x <> 0
-----
sgn(x) = abs(x) / ( x + isz(x) )
Out : 1 if x>0 , 0 if x = 0 , -1 if x < 0
----
NOT (x) = isz (x)
----
cmp(a,b) = sgn(a-b)
Out : 1 if a>b , 0 if a=b, -1 if a<b
-----
isnz(x) = abs( sgn(x) )
Out : 1 if a<>0 , 0 if a=0
---
ife(a,b) = isz(a-b)
Out : 1 if a=b , 0 if a<>b
--------------------
ifg(a,b) = isz(cmp(a,b)-1)
Out : 1 if a>b , 0 if a<b
--------
ifl(a,b) = isz(cmp(a,b)+1)
Out : 1 if a<b , 0 if a>b

Source : dirbax

I typed up a long reply to you before but decided to save it. One thing I think that is horrible with your notation is your use of functions like isnz, ife, etc etc. Ultimately they're insufficient for representing branching, because multiplication by zero doesn't save you from infinite recursion.

I wrote the following reply several days ago but decided not to send it. One problem with it is that it treats things at a high level -- it is treating entire if blocks as if they were single statements converted straight into some kind of mathematical notation. There is only one example of using an expression, which can modify state _and_ needs to return a value. Another is that it kind of glosses over the construction of a for loop.

One problem you have is that you just kind of throw the plus operator in there, all magically.

Really, your scheme for converting C++ functions into "mathematics" is nothing more than devising a programming language and poorly specifying a compiler from C++ to that language.

Here is my original reply, which might affect your perspective on this problem somewhat.


----

For example, I'd do it as follows. Quoting your code for convenience:

int F( int n )
{
    int r=0;                    // A
    int mid=n/2;                // B
    for( int i=0 ; i<n ; i++)   // C
    {
        if( i<mid) r+=1 ;
        if( i==mid) r*=2 ;
        if( i>mid) r=pow(r,3) ;
    }
    return r ;                  // D
}

First, treat every statement and block like a function that inputs and outputs an ordered pair containing all the variables in scope before and after the statement.

Let's look at the types of these functions (which, for readability, name the variables the inputs and outputs correspond to):

A :: int n -> (int n, int r)
B :: (int n, int r) -> (int n, int r, int mid)
C :: (int n, int r, int mid) -> (int n, int r, int mid)
D :: (int n, int r, int mid) -> int

I'm not really sure how to treat return statements like D, so maybe some more thought is needed on that matter.

I hope these type definitions are clear. For example, B is a function that takes an ordered pair with two ints and returns an ordered triple with three ints.

We can supply definitions for A and B and D easily -- we of course need some work for the for loop, C. These definitions describe how the statement modifies the variables they have in scope. The variables are in some sense 'inputs' to the statement/function and the output is the new set of values contained in these variables.

A(n) = (n, 0)
B(n, r) = (n, r, div(n, 2))  // div is integer division
C(n, r, mid) = ...           // holding off on this
D(n, r, mid) = r

Now let's look at the for loop.

for( int i=0 ; i<n ; i++)   // blah
{
    if( i<mid) r+=1 ;             // E  //
    if( i==mid) r*=2 ;            // F  // Interior
    if( i>mid) r=pow(r,3) ;       // G  // 
}

We can know write down the types of the blocks E, F, and G -- they start and end with the same set of variables in scope.

E :: (int n, int r, int mid, int i) -> (int n, int r, int mid, int i)
F :: (int n, int r, int mid, int i) -> (int n, int r, int mid, int i)
G :: (int n, int r, int mid, int i) -> (int n, int r, int mid, int i)

As for implementations, that's a little tricky. You created some functions like ifl and such which I think are disgusting. I'm just going to use some custom 'if then else' notation.

E(n, r, mid, i) = if i < mid then (n, r + 1, mid, i) else (n, r, mid, i)
F(n, r, mid, i) = if i == mid then (n, r * 2, mid, i) else (n, r, mid, i)
G(n, r, mid, i) = if i > mid then (n, r ^ 3, mid, i) else (n, r, mid, i)

We can then regard the entire interior of the for loop as a composition of functions:

Interior(n, r, mid, i) = G(E(F(n, r, mid, i)))

Now, we need to handle the mechanism of the for loop. The truth is that there are three statements or expressions explicitly written: the statement " int i = 0; " (H), the expression " i < n " (I), and the statement " i++ " (J).

We can decode that as follows. The first statement, H, introduces a new variable. Here's its type an implementation:

H :: (int n, int r, int mid) -> (int n, int r, int mid, int i)
H(n, r, mid) = (n, r, mid, 0)

Let's skip I for now. Looking at J, its behavior is simple to describe:

J :: (int, int, int, int) -> (int, int, int, int)
J(n, r, mid, i) = (n, r, mid, i + 1)

Finally we have the function I, which corresponds to a C++ expression. Expressions can have side effects, modifying variables, and they also have a return value. We'll write the expression as a function that takes as input the variables that are in scope, and as output an ordered pair, which contains a return value (boolean in this case) and the tuple of variables, in case they were modified.

I :: (int, int, int, int) -> (bool, (int, int, int, int))
I(n, r, mid, i) = (i < n, (n, r, mid, i))

Now, we have the three statements of a for loop, H, I, and J, and we have the inner block, Interior. So, in combining them, let's make a function C'. I'd like to write C, but we haven't made a function that takes the variable i out of scope yet.

C' :: (int n, int r, int mid) -> (int n, int r, int mid, int i)
C'(n, r, mid) = Looper(H(n, r, mid))
 
Looper :: (int n, int r, int mid, int i) -> (int n, int r, int mid, int i)
Looper(n, r, mid, i) = let (test, newVars) = I(n, r, mid, i)
                       in if test
		          then Looper(J(Interior(newVars)))
		          else newVars

Finally, we need a function that corresponds to the closing brace, that takes variables out of scope:

deScopeC :: (int, int, int, int) -> (int, int, int)
deScopeC(n, r, mid, i) = (n, r, mid)

Then we can write C:

C :: (int, int, int) -> (int, int, int)
C(n, r, mid) = deScopeC(C'(n, r, mid))

And finally we can write our function F, mathematically. I'm naming it FF because I already used F.

FF :: int -> int
FF(n) = D(C(B(A(n))))

Putting it all together:

A :: int -> (int, int)
A(n) = (n, 0)
B :: (int, int) -> (int, int, int)
B(n, r) = (n, r, div(n, 2))
D :: (int, int, int) -> int
D(n, r, mid) = r
 
E :: (int, int, int, int) -> (int, int, int, int)
E(n, r, mid, i) = if i < mid then (n, r + 1, mid, i) else (n, r, mid, i)
 
F :: (int, int, int, int) -> (int, int, int, int)
F(n, r, mid, i) = if i == mid then (n, r * 2, mid, i) else (n, r, mid, i)
 
G :: (int, int, int, int) -> (int, int, int, int)
G(n, r, mid, i) = if i > mid then (n, r ^ 3, mid, i) else (n, r, mid, i)
 
H :: (int n, int r, int mid) -> (int n, int r, int mid, int i)
H(n, r, mid) = (n, r, mid, 0)
 

Interior :: (int, int, int, int) -> (int, int, int, int)
Interior(n, r, mid, i) = G(E(F(n, r, mid, i)))
 
J :: (int, int, int, int) -> (int, int, int, int)
J(n, r, mid, i) = (n, r, mid, i + 1)
 
I :: (int, int, int, int) -> (bool, (int, int, int, int))
I(n, r, mid, i) = (i < n, (n, r, mid, i))
 
C' :: (int, int, int) -> (int, int, int, int)
C'(n, r, mid) = Looper(H(n, r, mid))
 
Looper :: (int, int, int, int) -> (int, int, int, int)
Looper(n, r, mid, i) = let (test, newVars) = I(n, r, mid, i)
                       in if test
		          then Looper(J(Interior(newVars)))
		          else newVars 

deScopeC :: (int, int, int, int) -> (int, int, int)
deScopeC(n, r, mid, i) = (n, r, mid) 

C :: (int, int, int) -> (int, int, int)
C(n, r, mid) = deScopeC(C'(n, r, mid)) 

FF :: int -> int
FF(n) = D(C(B(A(n))))

And we could (not by accident) translate this easily to Haskell code:

a :: Int -> (Int, Int)
a(n) = (n, 0)
b :: (Int, Int) -> (Int, Int, Int)
b(n, r) = (n, r, div n 2)
d :: (Int, Int, Int) -> Int
d(n, r, mid) = r
 
e :: (Int, Int, Int, Int) -> (Int, Int, Int, Int)
e(n, r, mid, i) = if i < mid then (n, r + 1, mid, i) else (n, r, mid, i)
 
f :: (Int, Int, Int, Int) -> (Int, Int, Int, Int)
f(n, r, mid, i) = if i == mid then (n, r * 2, mid, i) else (n, r, mid, i)
 
g :: (Int, Int, Int, Int) -> (Int, Int, Int, Int)
g(n, r, mid, i) = if i > mid then (n, r ^ 3, mid, i) else (n, r, mid, i)
 
h :: (Int, Int, Int) -> (Int, Int, Int, Int)
h(n, r, mid) = (n, r, mid, 0)
 

interior :: (Int, Int, Int, Int) -> (Int, Int, Int, Int)
interior(n, r, mid, i) = g(e(f(n, r, mid, i))) 

j :: (Int, Int, Int, Int) -> (Int, Int, Int, Int)
j(n, r, mid, i) = (n, r, mid, i + 1) 

ii :: (Int, Int, Int, Int) -> (Bool, (Int, Int, Int, Int))
ii(n, r, mid, i) = (i < n, (n, r, mid, i)) 

c' :: (Int, Int, Int) -> (Int, Int, Int, Int)
c'(n, r, mid) = looper(h(n, r, mid)) 

looper :: (Int, Int, Int, Int) -> (Int, Int, Int, Int)
looper(n, r, mid, i) = let (test, newVars) = ii(n, r, mid, i)
                       in if test
		          then looper(j(interior(newVars)))
		          else newVars 

deScopec :: (Int, Int, Int, Int) -> (Int, Int, Int)
deScopec(n, r, mid, i) = (n, r, mid) 

c :: (Int, Int, Int) -> (Int, Int, Int)
c(n, r, mid) = deScopec(c'(n, r, mid))
 
ff :: Int -> Int
ff(n) = d(c(b(a(n))))
This article has been dead for over six months. Start a new discussion instead.