I'm looking for a more concise way to compare a variable to a range of numbers in Structure Text (ST) - st

I am trying to find a more concise way to compare a variable to a range of numbers.
Currently I do:
IF int_variable=67 or int_variable=68 or int_variable=69 then...
Is there a way to write something like: IF int_variable=67 through 69 then
Thanks in advance.

If you really mean that if the variable is in range of those numbers, it's just simple as this. But in more complex situations you have no shortcuts, just use Jakobs method or similar.
IF int_variable >= 67 AND int_variable <= 69 THEN
//It is 67, 68, or 69
END_IF

You could for example use a for-loop, like:
FOR nCounter := 67 to 69 by 1 DO
IF int_variable = nCounter THEN
....
EXIT; // If you want to exit the loop
END_IF
END_FOR

If the comparisons are always integers (or an enumerated type) you can use a case statement.
CASE example_int OF
1,2: <do whatever you need to do>
4,5,7,8: <do other stuff>
ELSE
<do default case stuff>
END_CASE
If you need larger ranges you'll just have to use AND or nested IFs (nested IFs shown below)
IF example_int >= 2 THEN
IF example_int < 5 THEN
//in range 2 - 5
ELSIF example_int <= 10 THEN
//in range 6 - 10
END_IF
END_IF
Remember to be mindful of the end points. If you forget the "or-equals" portion in either of the IF statements above, it changes the range

There is no other way to check if the condition is ok like you want to do. In ST, you can code Library & function, if you have too much condition, you can code a library who resolve your problem. But it's useless because ST allow to order code to be readable. Like below :
IF (n>=0) AND (n<=20) OR
(n>=32) AND (n<=45) THEN
// Do this
ELSE
// Do that
END_IF ;
But you can call a function or library to fill a boolean var with TRUE or FALSE. You will just need to test the var in a logic loop.
//IN_aTestValues & aValueToTest are an Array of values
bVarTest := TestCond( IN_aTestValues := aValueToTest );
If bVarTest THEN
// Do this
ELSE
// Do that
END_IF ;
You can also do :
bVar := bToTest = 67 AND
bToTest = 84 AND
bToTest > 47 AND
NOT (bToTest = 25) ;
IF bVar THEN
// Do this
Else
// Do That
END_IF ;

Related

Pinescript variable doesn't change its value

So I have a problem, thought a lot about it but not able to fix it so I would appreciate some help from you.
To make it simple, I'll give another piece of code.
currentRSI = ta.rsi(close,14)
var tradeExists = 0
if (currentRSI > 50 and tradeExists == 0)
tradeExists := 1
alert("Long trade")
In my case, if currentRSI crosses over 50, so it gets to 51, AND in the same candle of the timeframe it gets to 49.5, the tradeExists value will remain 0 but the alert has been sent
how could I fix to detect that and close the trade, any idea if I can do this?
I want to specify that I also tried using varip tradeExists = 0 but the variable still gets rollback at the close of the candle.
I just had that problem and I fixed it: use
the barstate.isconfirmed in your conditions, it's the only way to change a var in pinescript.
if (barstate.isconfirmed and first_time_signal == false)
if nT3Average >= ok_to_buy and nT3Average_2 <= oversold
last_signal := 1
label.new(bar_index,close,'Long',color=color.rgb(49, 161, 64),style = label.style_label_up,xloc=xloc.bar_index,yloc=yloc.belowbar)
first_time_signal := true
if nT3Average <= ok_to_sell and nT3Average_2 >= overbought
last_signal := -1
label.new(bar_index,close,'Short',color=color.rgb(175, 55, 95),style = label.style_label_down,xloc=xloc.bar_index,yloc=yloc.abovebar,textcolor=color.rgb(10,10,10))
first_time_signal := true

How to print ONCE if there are multiple correct answers? (MATLAB)

So I have arr = randi([0,20],20,1). I want to show: If there are numbers less than 5, fprintf('Yes\n') only once. Im using a for loop (for i = 1 : length(arr)) and indexing it.
As your description, maybe you need if statement within for loop like below
for i = 1:length(arr)
if arr(i) < 5
fprintf('Yes\n');
break
end
end
If you want to print Yes once, you can try
if any(arr < 5)
fprintf('Yes\n')
endif
If you don't want to use break, the code below might be an option
for i = 1:min(find(arr <5))
if (arr(i) < 5)
fprintf('Yes\n');
end
end
You can use a break statement upon finding the first value under 5 and printing the Yes statement.
Using a break Statement:
arr = randi([0,20],20,1);
for i = 1: length(arr)
if arr(i) < 5
fprintf("Yes\n");
break;
end
end
Extension:
By Using any() Function:
Alternatively, if you'd like to concise it down without the need for a for-loop the any() function can be used to determine if any values within the array meet a condition in this case arr < 5.
arr = randi([0,20],20,1);
if(any(arr < 5))
fprintf("Yes\n");
end
By Using a While Loop:
Check = 0;
arr = randi([0,20],20,1);
i = 1;
while (Check == 0 && i < length(arr))
if arr(i) < 5
fprintf("Yes\n");
Check = 1;
end
i = i + 1;
end

How to print the variable and use it from the if sentence in windbg script?

1,For how to print the variable, I used the following sentence with windbg script, however it fail to print it.
r #$t0 = 123;
.printf #$t0
2,How to use the variable in if sentence, however I still found it failed.
r #$t0 = 123;
.if(#$t0 ==123)
{
.printf #$t0
}
How to modify them?
I think your way to use pseudo-register isn't wrong, but:
1) .printf() takes a format string as it does in C
2) By default, numbers are in Hex rather than decimals, use 0n or 0x to mention their base explicitly
3) Historically you shouldn't have used '#' to set a pseudo register with 'r', although I believe now it works in either way
r $t0 = 0n123;
.if ( #$t0 == 0n123 )
{
.printf "%d", #$t0
}
$$ sum of triangular numbers in windbg script
r eax=0;r $t0=0;.while(#$t0<10){r eax=#eax+#$t0;.printf "%2d=%3d\n",#$t0,#eax;r $t0=#$t0+1}
result
0= 0
1= 1
2= 3
3= 6
4= 10
5= 15
6= 21
7= 28
8= 36
9= 45
10= 55
11= 66
12= 78
13= 91
14=105
15=120
lets confirm f(n) = n * (n+1) /2
? 0n15 * (0n16/2)
Evaluate expression: 120 = 00000078

Maple: RNG is not random

i was "finding Pi" with Monte Carlo Method, but the answer was incorrect. The oryginal code was:
RandomTools[MersenneTwister]: with(Statistics):
tries := 10000:
s := 0;
for i to tries do
if GenerateFloat()^2+GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
It gives answer aroud 2.8-2.85
when I change the code to
s := 0;
x := Array([seq(GenerateFloat(), i = 1 .. tries)]);
y := Array([seq(GenerateFloat(), i = 1 .. tries)]);
for i to tries do
if x[i]^2+y[i]^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
Then the answer is correct. I have no idea why i can't generate number in "for" loop.
I've founded that the mean of it is the same, but the variance is different.
For:
tries := 100000;
A := Array([seq(GenerateFloat(), i = 1 .. 2*tries)]);
s1 := Array([seq(A[i]^2+A[tries+i]^2, i = 1 .. tries)]);
Mean(s1);
Variance(s1);
s2 := Array([seq(GenerateFloat()^2+GenerateFloat()^2, i = 1 .. tries)]);
Mean(s2);
Variance(s2);
output is:
0.6702112097021581
0.17845439723457215
0.664707674135025
0.35463131700965245
What's wrong with it? GenerateFloat() should be as uniform as possible.
Automatic simplification is turning your,
GenerateFloat()^2+GenerateFloat()^2
into,
2*GenerateFloat()^2
before GenerateFloat() is evaluated.
One simple change to get it to work as you expected would be separate them. Eg,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
for i to tries do
t1,t2 := GenerateFloat(),GenerateFloat();
if t1^2+t2^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);
Another way is to use a slightly different construction which doesn't automatically simplify. Consider, single right quotes (uneval quotes) don't stop automatic simplification (which is a definition of the term if you want).
'f()^2 + f()^2';
2
2 f()
But the following does not automatically simplify,
a:=1:
'f()^2 + a*f()^2';
2 2
f() + a f()
Therefore another easy workaround is,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
a := 1;
for i to tries do
if GenerateFloat()^2 + a*GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);

Printing symbol name and value in Mathematica

I'd like to create a function My`Print[args__] that prints the names of the symbols that I pass it, along with their values. The problem is that before the symbols are passed to My`Print, they're evaluated. So My`Print never gets to see the symbol names.
One solution is to surround every argument that I pass to My`Print with Unevaluated[], but this seems messy. Is there a way of defining a MACRO such that when I type My`Print[args__], the Mathematica Kernel sees My`Print[Unevaluated /# args__]?
You need to set the attribute HoldAll on your function, with SetAttribute[my`print].
Here's a possible implementation:
Clear[my`print]
SetAttributes[my`print, HoldAll]
my`print[args__] :=
Scan[
Function[x, Print[Unevaluated[x], " = ", x], {HoldAll}],
Hold[args]
]
I used lowercase names to avoid conflicts with built-ins or functions from packages.
EDIT:
Just to make it explicit: I have two functions here. One will print the value of a single symbol, and is implemented as a Function inside. You can just use this on its own if it's sufficient. The other is the actual my`print function. Note that both need to have the HoldAll attribute.
ClearAll[My`Print]
SetAttributes[My`Print, HoldAll]
My`Print[args___] :=
Do[
Print[
Extract[Hold[args], i, HoldForm], "=", List[args][[i]]
], {i, Length[List[args]]}
]
ape = 20;
nut := 20 ape;
mouse = cat + nut;
My`Print[ape, nut, mouse]
(* ==>
ape=20
nut=400
mouse=400+cat
*)
SetAttributes[MyPrint, HoldAll];
MyPrint[var_] :=
Module[
{varname = ToString[Hold[var]]},
Print[StringTake[varname, {6, StringLength[varname] - 1}],
" = ", Evaluate[var]]
]
Coming late to the party - one can use Listability to get a rather elegant (IMO) solution avoiding explicit loops or evaluation control constructs:
ClearAll[prn];
SetAttributes[prn, {HoldAll, Listable}];
prn[arg_] := Print[HoldForm[arg], " = ", arg];
prn[args___] := prn[{args}]
Stealing the test case from #Sjoerd,
In[21]:= prn[ape,nut,mouse]
During evaluation of In[21]:= ape = 20
During evaluation of In[21]:= nut = 400
During evaluation of In[21]:= mouse = 400+cat
Out[21]= {Null,Null,Null}
Here is another variation of My`Print to add to the mix:
ClearAll[My`Print]
SetAttributes[My`Print, HoldAll]
My`Print[expr_] := Print[HoldForm[expr], " = ", expr]
My`Print[exprs___] := Scan[My`Print, Hold[exprs]]
... and another...
ClearAll[My`Print]
SetAttributes[My`Print, HoldAll]
My`Print[args___] :=
Replace[
Unevaluated # CompoundExpression # args
, a_ :> Print[HoldForm[a], " = ", a]
, {1}
]
Either way, the use is the same:
$x = 23;
f[x_] := 1 + x
My`Print[$x, $x + 1, f[1]]
(* prints:
$x = 23
$x+1 = 24
f[1] = 2
*)
In addition to the other answers consider the functions DownValues, OwnValues and UpValues:
In[1] := f[x_] := x^2
In[2] := f[x_, y_] := (x + y)^2
In[3] := DownValues[f]
Out[3] = {HoldPattern[f[x_]] :> x^2, HoldPattern[f[x_, y_]] :> (x + y)^2}
http://reference.wolfram.com/mathematica/ref/DownValues.html