# Data types, variables and operations

NetSimLan knows the data types `node`

, `int`

, `float`

, `string`

and `bool`

.
Most of them you already know.
You can create a variable *v* of one of this types with `type v;`

as we did before or with `type v=e;`

where *e* is a value or expression for a value which will be assigned to *v*.

Whenever a variable is declared by no value is assigned yet, it has a default value. Try it out: add the following method to your grid-example and run it on one node:

```
defaultValues(){
node n; print (n);
int i; print (i);
float f; print (f);
string s; print (s);
bool b; print (b);
}
```

To sum this up, here’s a overview for the types:

Type | possible values | default value | meaning of default |
---|---|---|---|

node |
`this` , `null` or any node |
`null` |
no node |

int |
`MIN_INTEGER` to `MAX_INTEGER` |
`0` |
0 |

float |
floating numbers, `POSITIVE_INFINITY` , `NEGATIVE_INFINITY` , `PI` , `E` , `NaN` |
`NaN` |
not a number |

string |
strings | `""` |
empty string |

bool |
`true` , `false` |
`false` |
false |

## Expressions and arithmetic operations

You’ve already seen expressions in the former examples for example *(id(this)-1)/size*.
This section is to give you an overview about the possible operations in expressions and special cases.

Integers and floats can be combined with `+-*/`

as you would expect from any programming language.
You can also use the power function `a^^b`

meaning *a to the power of b*.
For integers you can use the modulo operator `%`

.
Whenever a not solvable arithmetic exception occurs e.g. *5/0*, the inner method call producing that error is canceled and a message is printed to the output. The rest of the method stack continues.

When you combine an integer and a float you’ll receive a float. To turn this in an integer you can use `round`

rounding to the next integer. Be aware, this is a correct round, not a simple floor.
In context that may looks as follows:

```
int i; i=round((2*2.5)/2.0); /* now i == 3 */
```

You can also calculate the square root of a number *n* using `sqrt(n)`

, the logarithm (base 2) of *n* using `log(n)`

or get a random integer between 0 (inclusive) and *n* (exclusive) using `random(n)`

.

To work with geometry, the trigonometric functions, inverse trigonometric functions and hyperbolic functions `sin(a)`

, `cos(a)`

, `tan(a)`

, `arcsin(a)`

, `arccos(a)`

, `arctan(a)`

, `sinh(a)`

, `cosh(a)`

, `tanh(a)`

for a value *a* can be used. All of these functions use radiant for angles, meaning for example that `sin(PI)==0`

holds.

Numbers can be compared using `==`

, `!=`

, `<=`

, `<`

, `>=`

and `>`

.

Anything can be compared to a string using the `+`

, e.g. `5+"edges"`

. We’ll see how to do more complex things with strings next chapter.

Boolean expressions *a* and *b* can be negated `!a`

or combined with *and* `a&b`

, *or* `a|b`

and *xor* `a^b`

.

All of this expressions can be structured using brakes `()`

.

## Node Types and Hash Functions

As you’ve seen you can access a node’s id with `id(n)`

, where *n* is an expression for the node.
You can also get a type of a node as a string. That’s useful for networks with different node types, e.g. server and client.
For example you can get a nodes own type with `string myType = type(this);`

.

You may hash any datatype to an integer with tree different hash functions `hash`

, `hash2`

and `hash3`

.
All of them get one parameter to hash and return an integer between `MIN_INTEGER`

and `MAX_INTEGER`

, but map a given value to different results.
There are three function for the case you need different hash functions in you algorithm, e.g. to store something redundantly over different nodes.
Let’s use the hash functionality: Open your grid-example again and add a new function for sending a message and calculate the hash of the text. That may looks as follows:

```
startMessage(string text, int to_id){
message(text,to_id,hash(text));
}
```

Now you need to extend a your *message* function by a parameter *int hashValue*. Take care to forward it by every recursive call.
Instead of just printing the message, you can check the hash value. For example as follows:

```
if (hash(text) == hashValue){
print("Message " + text + " received.");
}else{
print("Message with wrong hash occured");
}
```

Now try it out: Start the grid and send a message with *startMessage*. It should end as we used to know.
Afterwards send a message with the *message* function and an arbitrary hash. That will most likely end with a message from the goal node saying the hash is wrong.
If you like you can change your program, such that a hash isn’t just hashing the text but the text and the goal node. Or you can check the hash in every step and give the error message by the first node checking the message instead of the goal node.

## Coordinates

So far we had a fixed routing protocol first fixing the x, second the y dimension.
Let’s turn of the auto position and imagine the positions in the graph where real positions and some nodes are on positions far away from others.
We’d like to change the routing protocol as follows: If the x or the x dimension is wrong but the other is correct, route along the wrong one.
If both are wrong, route along that dimension on which the next hop is closer to the current one.
We can get every nodes coordinates as *float* with the build in functions `longitude`

and `latitude`

.
In total the rewrite of the *message* function may looks as follows:

```
message (string text, int to_id, int hashValue){
int x_n=(to_id-1)/size; int y_n=(to_id-1)%size;
if (x_n == x_this & y_n == y_this){
if (hash(text) == hashValue){
print("Message " + text + " received.");
}else{
print("Message with wrong hash occured");
}
} else if (x_n != x_this & y_n == y_this) {
if (x_n < x_this)
left -> message(text, to_id, hashValue);
else right -> message(text, to_id, hashValue);
} else if (x_n == x_this & y_n != y_this) {
if (y_n < y_this)
bottom -> message(text, to_id, hashValue);
else top -> message(text, to_id, hashValue);
} else {
node next_x; node next_y;
if (x_n < x_this) next_x = left;
else next_x = right;
if (y_n < y_this) next_y = bottom;
else next_y = top;
float distance_x = sqrt(
(longitude(next_x)-longitude(this))^^2 +
(latitude(next_x)-latitude(this))^^2 );
float distance_y = sqrt(
(longitude(next_y)-longitude(this))^^2 +
(latitude(next_y)-latitude(this))^^2 );
if (distance_x < distance_y)
next_x -> message(text, to_id, hashValue);
else next_y -> message(text, to_id, hashValue);
}
mark (true);
}
```

## Functions with return values

You may notice, in the last code we do the same thing for different values. NetSimLan also offers return values. This is of cause only possible for local function calls and not for remote ones. A function to calculate this distance may looks as follows:

```
distance float (node n){
float d = sqrt(
(longitude(n)-longitude(this))^^2 +
(latitude(n)-latitude(this))^^2 );
return d;
}
```

Please note, the return type is behind the function name.

The calculation of distances in the message function reduces to the following lines:

```
float distance_x = distance(next_x);
float distance_y = distance(next_y);
```

Previous: Debugging Next: Arrays and Loops