| User-Defined Opcode Database |
|---|
Calculates a binary numerical expression in a string and returns the result as a number. One of the elements can be itself a binary expression, in which case it must be set in parentheses. Requires the UDO StrExpr1
Download UDO FileCalculates a binary numerical expression in a string and returns the result as a number. One of the elements can be itself a binary expression, in which case it must be set in parentheses. No spaces are allowed. Supported math operations are +, -, *, /, ^, and %. A simple number string or a simple expression (like in StrExpr1) is also accepted and converted to a number.
Requires the UDO StrExpr1.
iNum StrExpr2 Str
Str - Input string with a binary math expression. One of the elements can be itself a binary expression, in which case it must be set in parentheses. No spaces are allowed. Supported math operations are +, -, *, /, ^, and %. A simple number string or a simple expression (like in StrExpr1) is also accepted and converted to a number.
iNum - result of the binary operation as number
opcode StrExpr2, i, S
Sin xin
ilen strlen Sin
;if a parenthesis can be found
iparenth strindex Sin, "("
if iparenth > -1 then
;if in first half and no '-' preceeds
if iparenth == 0 then
;then first element ends in ")"
iprend strindex Sin, ")"
S1 strsub Sin, 1, iprend
;convert this element into a number
i1 StrExpr1 S1
;append the rest and convert again
S2 strsub Sin, iprend+2
Sep strsub Sin, iprend+1, iprend+2
Scoll sprintf "%f%s%s", i1, Sep, S2
ires StrExpr1 Scoll
;if in first half and '-' preceeds
elseif iparenth == 1 then
;then first element ends in ")"
iprend strindex Sin, ")"
S1 strsub Sin, 2, iprend
;convert this element into a number
i1 StrExpr1 S1
i1 = -i1
;append the rest and convert again
S2 strsub Sin, iprend+2
Sep strsub Sin, iprend+1, iprend+2
Scoll sprintf "%f%s%s", i1, Sep, S2
ires StrExpr1 Scoll
;if the parenthesis is in the second half
else
;isolate first element and the conjunction
S1 strsub Sin, 0, iparenth-1
Sep strsub Sin, iparenth-1, iparenth
;convert the second element
S2 strsub Sin, iparenth+1, ilen-1
i2 StrExpr1 S2
;if subtraction and i2 negative, convert to addition
isepminus strcmp Sep, "-"
if i2 < 0 && isepminus == 0 then
i2 = -i2
Sep = "+"
endif
;convert the whole
Scoll sprintf "%s%s%f", S1, Sep, i2
ires StrExpr1 Scoll
endif
;if no parenthesis, simply convert
else
ires StrExpr1 Sin
endif
xout ires
endop
<CsoundSynthesizer>
<CsOptions>
-nm0
</CsOptions>
<CsInstruments>
opcode StrExpr1, i, S
Str xin
isum strindex Str, "+"; sum
idif strindex Str, "-"; difference
ipro strindex Str, "*"; product
irat strindex Str, "/"; ratio
ipow strindex Str, "^"; power
imod strindex Str, "%"; modulo
if ipow > 0 then
ifirst strindex Str, "^"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 ^ i2
elseif imod > 0 then
ifirst strindex Str, "%"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 % i2
elseif ipro > 0 then
ifirst strindex Str, "*"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 * i2
elseif irat > 0 then
ifirst strindex Str, "/"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 / i2
elseif isum > 0 then
ifirst strindex Str, "+"
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
i1 strtod S1
i2 strtod S2
ires = i1 + i2
elseif idif > -1 then
ifirst strrindex Str, "-";(last occurrence: -3-4 is possible, but not 3--4)
S1 strsub Str, 0, ifirst
S2 strsub Str, ifirst+1
iS1len strlen S1
if iS1len == 0 then ;just a negative number
inum strtod S2
ires = -inum
else
ifirst strtod S1
isec strtod S2
ires = ifirst - isec
endif
else
ires strtod Str
endif
xout ires
endop
opcode StrExpr2, i, S
Sin xin
ilen strlen Sin
;if a parenthesis can be found
iparenth strindex Sin, "("
if iparenth > -1 then
;if in first half and no '-' preceeds
if iparenth == 0 then
;then first element ends in ")"
iprend strindex Sin, ")"
S1 strsub Sin, 1, iprend
;convert this element into a number
i1 StrExpr1 S1
;append the rest and convert again
S2 strsub Sin, iprend+2
Sep strsub Sin, iprend+1, iprend+2
Scoll sprintf "%f%s%s", i1, Sep, S2
ires StrExpr1 Scoll
;if in first half and '-' preceeds
elseif iparenth == 1 then
;then first element ends in ")"
iprend strindex Sin, ")"
S1 strsub Sin, 2, iprend
;convert this element into a number
i1 StrExpr1 S1
i1 = -i1
;append the rest and convert again
S2 strsub Sin, iprend+2
Sep strsub Sin, iprend+1, iprend+2
Scoll sprintf "%f%s%s", i1, Sep, S2
ires StrExpr1 Scoll
;if the parenthesis is in the second half
else
;isolate first element and the conjunction
S1 strsub Sin, 0, iparenth-1
Sep strsub Sin, iparenth-1, iparenth
;convert the second element
S2 strsub Sin, iparenth+1, ilen-1
i2 StrExpr1 S2
;if subtraction and i2 negative, convert to addition
isepminus strcmp Sep, "-"
if i2 < 0 && isepminus == 0 then
i2 = -i2
Sep = "+"
endif
;convert the whole
Scoll sprintf "%s%s%f", S1, Sep, i2
ires StrExpr1 Scoll
endif
;if no parenthesis, simply convert
else
ires StrExpr1 Sin
endif
xout ires
endop
instr 1
String strget p4
iNum StrExpr2 String
printf_i "'%s' -> %f\n", 1, String, iNum
endin
</CsInstruments>
<CsScore>
i 1 0 .01 "1" ;simple number string
i 1 + .01 "1+1" ;simple binary expression
i 1 + .01 "(1+1)+1" ;binary expression with one nested expression
i 1 + .01 "1+(1+1)"
i 1 + .01 "(1-1)-1"
i 1 + .01 "1-(1-1)"
i 1 + .01 "-(1-1)-1"
i 1 + .01 "-1-(1-1)"
i 1 + .01 "(2-1)-1"
i 1 + .01 "2-(1-1)"
i 1 + .01 "-(2-1)-1"
i 1 + .01 "(1-2)-1"
i 1 + .01 "1-(2-1)"
i 1 + .01 "-(1-2)-1"
i 1 + .01 "(-2-1)-1"
i 1 + .01 "-2-(1-1)"
i 1 + .01 "-(-2-1)-1"
i 1 + .01 "(-1-1)-2"
i 1 + .01 "-1-(1-2)"
i 1 + .01 "-(-1-1)-2"
i 1 + .01 "123*0.456"
i 1 + .01 "123*-0.456" ;ok
i 1 + .01 "123*-(0.456)" ;no need for parentheses here, but also ok
i 1 + .01 "-123*-0.456"
i 1 + .01 "-(123*-0.456)"
i 1 + .01 "(-123*-0.456)"
i 1 + .01 "(1/2)/3"
i 1 + .01 "1/(2/3)"
i 1 + .01 "-(1/2)/3"
i 1 + .01 "(1/-2)/3"
i 1 + .01 "(-1/-2)/3"
i 1 + .01 "-(1/2)/-3"
i 1 + .01 "(1/2)/-3"
i 1 + .01 "-(-1/-2)/-3"
i 1 + .01 "2^(1/12)" ;equal tempered semitone
</CsScore>
</CsoundSynthesizer>
returns:
'1' -> 1.000000
'1+1' -> 2.000000
'(1+1)+1' -> 3.000000
'1+(1+1)' -> 3.000000
'(1-1)-1' -> -1.000000
'1-(1-1)' -> 1.000000
'-(1-1)-1' -> -1.000000
'-1-(1-1)' -> -1.000000
'(2-1)-1' -> 0.000000
'2-(1-1)' -> 2.000000
'-(2-1)-1' -> -2.000000
'(1-2)-1' -> -2.000000
'1-(2-1)' -> 0.000000
'-(1-2)-1' -> 0.000000
'(-2-1)-1' -> -4.000000
'-2-(1-1)' -> -2.000000
'-(-2-1)-1' -> 2.000000
'(-1-1)-2' -> -4.000000
'-1-(1-2)' -> 0.000000
'-(-1-1)-2' -> 0.000000
'123*0.456' -> 56.088000
'123*-0.456' -> -56.088000
'123*-(0.456)' -> -56.088000
'-123*-0.456' -> 56.088000
'-(123*-0.456)' -> 56.088000
'(-123*-0.456)' -> 56.088000
'(1/2)/3' -> 0.166667
'1/(2/3)' -> 1.499999
'-(1/2)/3' -> -0.166667
'(1/-2)/3' -> -0.166667
'(-1/-2)/3' -> 0.166667
'-(1/2)/-3' -> 0.166667
'(1/2)/-3' -> -0.166667
'-(-1/-2)/-3' -> 0.166667
'2^(1/12)' -> 1.059463
joachim heintz 2012
| Previous | Home | Next |
| StrExpr1 | StrNumP |