CopyPastor

Detecting plagiarism made easy.

Score: 0.8384235501289368; Reported for: String similarity Open both answers

Possible Plagiarism

Reposted on 2025-06-14
by Joe Boyle

Original Post

Original - Posted on 2025-04-14
by Joe Boyle



            
Present in both answers; Present only in the new answer; Present only in the old answer;

My requirement is a simple one. I just wanted to evaluate a numeric expression held as a character string like the following:
'(((456883899×45877)+533)/899955)'
To do this in a user scalar function I have had to write nearly 1500 lines of code. Whereas to do this in a stored procedure, using SP_EXECUTESQL, requires only eleven lines of code (but you can't use SP_EXECUTESQL in a function).
My code is below. you only get 40% of the functionality because stack overflow only allows 30,000 characters; whereas my full solution is 43,000 characters. However, once you get the code pattern, the other 40% is straightforward to write yourself.
The missing functionality is marked below with an x.
'(((non)on)on)'
'((non)o(non))'
'(no((non)on))'
'((no(non))on)' x
'(no(no(non)))' x
```
create or ALTER FUNCTION [dbo].[mthscnvrt11](@strng varchar(60)) RETURNS varchar(220) AS BEGIN
/*
This function takes in a numeric string from a varchar column and translates it to its numeric value.
In this data, the numeric strings always have 4 numbers, which are all integers, and three arithmetic operators.
All numeric string calculations pair two numbers within parantheses. E.g. '(((622788*57)*101)/1009)' or '(622788/((1009/57)/101))' etc... Which you, the eagle eyed observer might have noticesd are actually equivalent.
The value of @patern governs which section of code is executed.
This data which this function is designed to process, has only the 5 @patern values listed below, so that is all I have coded for.
'(((non)on)on)' '((non)o(non))' '(no((non)on))' '((no(non))on)' '(no(no(non)))'
The @patern symbols '(' and ')' control order of execution. The n's represent the 4 numbers, num1, num2, num3 and num4 from left to right. The o's represent the arithmetic operators, opo1, opo2 and opo3 from left to right.
We are only interested in the general form of @patern, not the details, so the 'replace' code below reduces @patern strings like '(((nnnnnnonn)onnn)onnnn)' or '(nnnnnno((nnnnonn)onnnn))' to the basic form: '(((non)on)on)' or (no((non)on)) etc.
*/

declare @ret1 varchar(20)
declare @ret2 varchar(180)
declare @ret3 varchar(100)
declare @where smallint
DECLARE @dbg smallint -- set @dbg= substring(@strng,1,1)
DECLARE @opo1 varchar(1) set @opo1='x'
DECLARE @opo2 varchar(1) set @opo2='x'
DECLARE @opo3 varchar(1) set @opo3='x'
DECLARE @opostrng varchar(3)
declare @num1_int int

declare @num1char varchar(10)
declare @num1cwnt smallint
set @num1char = '|'
set @num1cwnt = -1
set @num1_int = 0
declare @num2_int int
declare @num2char varchar(10)
declare @num2cwnt smallint
set @num2char = '|'
set @num2cwnt = -1

declare @num3_int int
declare @num3char varchar(10)
declare @num3cwnt smallint
set @num3char = '|'
set @num3cwnt = -1
declare @num4_int int
declare @num4char varchar(10)
declare @num4cwnt smallint
set @num4char = '|'
set @num4cwnt = -1
-- sql error line 7 !!!!!!!!!!
declare @sign varchar(1)
set @sign = ' '
declare @numerator_n38 numeric(38,0)
declare @denominator_n38 numeric(38,0)
declare @numerator_b_n38 numeric(38,0)
declare @denominator_b_n38 numeric(38,0)
declare @temp_holder_n38 numeric(38,0)
declare @division_n3820 numeric(38,20)
declare @division_b_n3820 numeric(38,20)
declare @dcmlpart_n3837 numeric(38,37)
declare @remndr_n3820 numeric(38,20)
declare @remndr_len_smallint smallint
declare @my_bigint bigint
declare @curval varchar(1)
declare @prevval varchar(1)
declare @mathstrng varchar(60)
declare @loopval smallint set @loopval=2
declare @strnglen smallint
declare @patern varchar(60)
declare @numflag smallint set @numflag=0

set @patern='('
set @prevval='('
-- set @mathstrng =substring(@strng,2,59) set @mathstrng =@strng
set @strnglen = len(@mathstrng)

-- This is the while loop which parses the pattern of the string -- -- @loopval begins at 2 because we know first char is always a '('

while @loopval <= @strnglen begin

-- gets each character from the string, 1 by 1
set @curval = substring(@mathstrng,@loopval,1)


if @curval = '(' or @curval = ')' begin set @patern=@patern+@curval end

-- constructs each of the arithmetic operators.
if @curval in ( '/','+','-','*') begin

-- builds the general pattern of the arithemetic expression
set @patern=@patern +'o'

-- begins construction of each of the arithmetic operators.
if @opo1='x' begin set @opo1 = @curval end
else if @opo2='x' begin set @opo2 = @curval end
else if @opo3='x' begin set @opo3 = @curval end
end -- if @opo1='x'
-- ends construction of each of the arithmetic operators.

-- below if block processes the 4 numeric stings
if @curval between '0' and '9' begin

-- builds the general pattern of the arithemetic expression
set @patern=@patern+'n'


-- below if block indicates which of the 4 number stings to process
if @num1cwnt = -1 begin set @numflag=1 -- set @num1cwnt=@loopval end
else if @num2cwnt = -1 and (@prevval not between '0' and '9') begin set @numflag=2 -- set @num2cwnt=@loopval end
else if @num3cwnt = -1 and (@prevval not between '0' and '9') begin set @numflag=3 -- set @num3cwnt=@loopval end
else if @num4cwnt = -1 and (@prevval not between '0' and '9') begin set @numflag=4 -- set @num4cwnt=@loopval end
-- End of block indicating which of the 4 number stings to process



-- begin if block indicates which of the 4 number stings we are constructing
if @numflag=1 begin set @num1char=@num1char+@curval end
else if @numflag=2 begin set @num2char=@num2char+@curval end
else if @numflag=3 begin set @num3char=@num3char+@curval end
else if @numflag=4 begin set @num4char=@num4char+@curval end
-- end if block indicating which of the 4 number stings we are constructing

end -- End if block processing the 4 numeric stings


-- keeps track of current, next and previous characters
set @loopval=@loopval+1 set @prevval = @curval

end
-- End of main while @loopval <= @strnglen


-- parsing is now complete
/* We are only interested in the general form of @patern, not the details, so the 'replace' code below reduces @patern strings like '(((nnnnnnonn)onnn)onnnn)' or '(nnnnnno((nnnnonn)onnnn))' to the basic form: '(((non)on)on)' or (no((non)on)) etc. */
set @patern = replace(@patern,'nnnnnnnnn','n') set @patern = replace(@patern,'nnnnnnnn','n') set @patern = replace(@patern,'nnnnnnn','n') set @patern = replace(@patern,'nnnnnn','n') set @patern = replace(@patern,'nnnnn','n') set @patern = replace(@patern,'nnnn','n') set @patern = replace(@patern,'nnn','n') set @patern = replace(@patern,'nn','n')

-- create each numeric value from its string value
set @num1_int = convert (int,substring(@num1char,2,9)) set @num2_int = convert (int,substring(@num2char,2,9)) set @num3_int = convert (int,substring(@num3char,2,9)) set @num4_int = convert (int,substring(@num4char,2,9))


-- the variable @opostrng helps to indicate which code to execute
set @opostrng=@opo1+@opo2+@opo3
--set @ret2 = @patern --@num1char+@num2char+@num3char+@num4char --goto mout

--set @ret2 = @patern --goto mout2
if @patern = '(((non)on)on)' --____________________________________________________ begin

--I am ((() this helps to navigate around the code

--set @ret2 = 'went into (((non)on)on)' --goto mout

-- this code processes expresssions of the form '(((n1 op1 n2) op2 n3) op3 n4)'
-- set numerator and denominator as required at each step
-- 1st performing (n1 op1 n2)

set @numerator_n38 = @num1_int
set @denominator_n38 = 1
-- __________________ process @opo1 and @num2_int _____________________
if @opo1 = '/' set @denominator_n38 = @denominator_n38 * @num2_int else if @opo1 = '-' set @numerator_n38 = @numerator_n38 - @num2_int else if @opo1 = '*' set @numerator_n38 = @numerator_n38 * @num2_int else if @opo1 = '+' set @numerator_n38 = @numerator_n38 + @num2_int
-- _________________ End process @opo1 and @num2_int ___________________


-- ___________________ process @opo2 and @num3_int _____________________

-- 2nd performing (X op2 n3)

if @denominator_n38 < 1.00000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo2 = '/' set @denominator_n38 = @denominator_n38 * @num3_int else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @num3_int else if @opo2 = '-' set @numerator_n38 = @numerator_n38 - @num3_int else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + @num3_int end
else begin
-- @denominator_n38 denominator is changed, so perform altered processing

-- operators @opo2 = '/' or @opo2 = '*' are not affected so process as normal
if @opo2 = '/' set @denominator_n38 = @denominator_n38 * @num3_int else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @num3_int
-- operators @opo2 = '-' or @opo2 = '+' must multiply by denominator before adding or subtracting
else if @opo2 = '-' set @numerator_n38 = @numerator_n38 - (@num3_int *@denominator_n38 ) else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + (@num3_int *@denominator_n38 )
end
-- ____________ End process @opo2 and @num3_int ________________


-- ______________ process @opo3 and @num4_int ___________________

-- 3rd performing (X op3 n4)
if @denominator_n38 < 1.000000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + @num4_int end

else begin
-- @denominator_n38 denominator is changed, so perform altered processing
-- operators @opo3 = '/' or @opo3 = '*' are not affected so process as normal
if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int



-- operators @opo3 = '-' or @opo3 = '+' must multiply by denominator before -- adding or subtracting
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - (@denominator_n38 * @num4_int) else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + (@denominator_n38 * @num4_int)

end
end

--____________ End process @opo3 and @num4_int ____________________
-- I am ((() this helps to navigate around the code

-- End if @patern = '(((non)on)on)' --______________________________________________


/* a/b / c/d = x/ c/d = xd/c = ad/bc ? 1/2 / 3/4 = 1.4/2.3 = 4/6 correct - so what ???
n1/n2 / n3/n4 == n1*n4 / n2*n3
or num/denom / num2/denom2 == num* denom2/ denom*num2
*/
-- ((non)o(non))
if @patern = '((non)o(non))' --____________________________________________________ begin

--I am (()) this helps to navigate around the code

-- Processing '((n1 op1 n2) op2 (n3 op3 n4)'
-- set numerator and denominator as required at each step
-- processing (n1 op1 n2)
set @numerator_n38 = @num1_int set @denominator_n38 = 1
-- __________________ process @num1_int @opo1 and @num2_int _____________________
if @opo1 = '/' set @denominator_n38 = @denominator_n38 * @num2_int else if @opo1 = '-' set @numerator_n38 = @numerator_n38 - @num2_int else if @opo1 = '*' set @numerator_n38 = @numerator_n38 * @num2_int else if @opo1 = '+' set @numerator_n38 = @numerator_n38 + @num2_int
-- REGARD THIS RESULT AS X
-- _________________ End process @num1_int @opo1 and @num2_int ___________________


-- processing (n3 op3 n4)
set @numerator_b_n38 = @num3_int set @denominator_b_n38 = 1
-- __________________ process @num3_int @opo3 and @num4_int _____________________
if @opo3 = '/' set @denominator_b_n38 = @denominator_b_n38 * @num4_int else if @opo3 = '-' set @numerator_b_n38 = @numerator_b_n38 - @num4_int else if @opo3 = '*' set @numerator_b_n38 = @numerator_b_n38 * @num4_int else if @opo3 = '+' set @numerator_b_n38 = @numerator_b_n38 + @num4_int
-- REGARD THIS RESULT AS Y
-- _________________ End process @num3_int @opo3 and @num4_int ___________________

-- __________________ process X @opo2 Y _____________________
set @where = 0
-- processes expressions with no '/' operators
if charindex( '/', @opostrng ) < 0.5 begin
--set @where = 1
if @opo2 = '-' set @numerator_n38 = @numerator_n38 - @numerator_b_n38 else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @numerator_b_n38 else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + @numerator_b_n38
end
-- processes expressions with at least one '/' operator
else if charindex( '/', @opostrng ) > 0.5 begin

-- processes expressions with only one central '/' operator. it does this by -- collapsing '/' characters within the 3 character string @opostrng, and then -- looking for a stringlength of two.
-- e.g. ((x-x)/(x+x)) , ((x*x)/(x+x)) etc
if ( @opo2 = '/' ) and ( len ( replace(@opostrng,'/','') ) =2 ) begin
-- n1-n2 / n3-n4 == num / num_b -- n1-n2 / n3+n4 == num / num_b -- n1*n2 / n3+n4 == num / num_b -- etc etc
set @where = 1
-- the denominator value is held in @numerator_b_n38 from above, but it has -- to be explicitly set here; the division is processed further along in this -- code (see below, near end)
set @denominator_n38 = @numerator_b_n38
end -- if ( @opo2 = '/' ) and ( len ( replace(@opostrng,'/','') ) =2 )
else begin
-- below processes expressions with one or more '/' operator.
set @numerator_n38 = @num1_int set @denominator_n38 = @num2_int set @numerator_b_n38 = @num3_int set @denominator_b_n38 = @num4_int

if @opostrng like '//_' begin
-- n1 / n2 / n3 ? n4 == num/denom / num_b ? denom_b

-- '///'
if @opo3 = '/' begin
-- n1/n2 / n3/n4 == num/denom / num_b/denom_b == num*denom_b / denom*num_b
-- this rearrangement significantly increases accuracy
set @numerator_n38 = @numerator_n38 * @denominator_b_n38 set @denominator_n38 = @denominator_n38 * @numerator_b_n38
end
-- '//*'
else if @opo3 = '*' set @denominator_n38 = ( @denominator_n38 * @numerator_b_n38 * @denominator_b_n38 )
-- '//-'
else if @opo3 = '-' set @denominator_n38 = ( @denominator_n38 * (@numerator_b_n38 - @denominator_b_n38) )
-- '//+'
else if @opo3 = '+' set @denominator_n38 = ( @denominator_n38 * (@numerator_b_n38 + @denominator_b_n38) )
end
-- ________________ End if @opostrng like '//_'

else if @opostrng like '/*_' begin
-- n1/n2 * n3/n4 == num/denom * num_b/denom_b == n1*n3/(n2*n4) -- == num*num_b / (denom*denom_b)
-- '/*/'
if @opo3 = '/' begin
set @numerator_n38 = @numerator_n38 * @numerator_b_n38 set @denominator_n38 = @denominator_n38 * @denominator_b_n38
end
-- n1/n2 * n3*n4 == num/denom * num_b*denom_b == (n1*n3*n4) /n2 -- == (num * num_b * denom_b)/denom
-- '/**'
else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @numerator_b_n38 * @denominator_b_n38
-- '/*-'
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 * (@numerator_b_n38 - @denominator_b_n38)
-- '/*+'
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 * (@numerator_b_n38 + @denominator_b_n38)
-- @denominator_n38 is already initialised
end
-- ________________ End else if @opostrng like '/*_'



else if @opostrng like '/+_' begin
-- n1/n2 + n3/n4 == num/denom + num_b/denom_b == ( n1*n4 + n2*n3 ) / (n2*n4) -- == ( (num-denom_b) + denom*num_b) ) / ( denom * denom_b )
-- '/+/'
if @opo3 = '/' begin
set @numerator_n38 = @numerator_n38 * @denominator_b_n38 set @numerator_n38 = @numerator_n38 + ( @denominator_n38 * @numerator_b_n38 )
set @denominator_n38 = @denominator_n38 * @denominator_b_n38
end
-- '/+*'
else if @opo3 = '*' set @numerator_n38 = @numerator_n38 + ( @denominator_n38 * @numerator_b_n38 * @denominator_b_n38 )
-- '/+-'
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 + ( @denominator_n38 *( @numerator_b_n38 - @denominator_b_n38 ) )
-- '/++'
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + ( @denominator_n38 *( @numerator_b_n38 + @denominator_b_n38 ) )
-- @denominator_n38 is already set correctly at initialisation
end
-- ________________ End else if @opostrng = '/+_'
else if @opostrng like '/-_' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b -- '/-?' == num - (numb * denom) / denom
-- '/-/'
if @opo3 = '/' begin
-- n1/n2 - n3/n4 == num/denom - num_b/denom_b == ( n1*n4 - n2*n3 ) / (n2*n4) -- == ( num*denom_b - denom*num_b ) )/ denom*denom_b
set @numerator_n38 = @numerator_n38 * @denominator_b_n38 set @numerator_n38 = @numerator_n38 - ( @denominator_n38 * @numerator_b_n38 ) set @denominator_n38 = @denominator_n38 * @denominator_b_n38
end
-- '/-*'
else if @opo3 = '*' set @numerator_n38 = @numerator_n38 - ( @denominator_n38 * @numerator_b_n38 * @denominator_b_n38 )
-- '/--'
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - ( @denominator_n38 *( @numerator_b_n38 - @denominator_b_n38 ) )
-- '/-+'
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 - ( @denominator_n38 *( @numerator_b_n38 + @denominator_b_n38 ) )
-- @denominator_n38 is already set correctly at initialisation
end
-- ________________ End else if @opostrng = '/-_'

else if @opostrng like '_-/' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b -- '/-?' == num - (numb * denom) / denom
-- a*b - c/d == (a*b*d )- c /d
-- '*-/'
if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @denominator_b_n38 ) - @numerator_b_n38
-- '--/'
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @denominator_b_n38 ) - @numerator_b_n38
-- '+-/'
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @denominator_b_n38 ) - @numerator_b_n38
set @denominator_n38 = @denominator_b_n38
end
-- ________________ End else if @opostrng like '_-/
else if @opostrng like '_+/' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b

if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @denominator_b_n38 ) + @numerator_b_n38
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @denominator_b_n38 ) + @numerator_b_n38
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @denominator_b_n38 ) + @numerator_b_n38
set @denominator_n38 = @denominator_b_n38

end
-- ________________ End else if @opostrng like '_+/'
else if @opostrng like '_*/' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b

if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @numerator_b_n38 )
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @numerator_b_n38 )
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @numerator_b_n38 )
set @denominator_n38 = @denominator_b_n38

end
-- ________________ End else if @opostrng like '_*/'

else if @opostrng like '_//' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b
if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @denominator_b_n38 )
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @denominator_b_n38 )
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @denominator_b_n38 )
set @denominator_n38 = @numerator_b_n38
end -- _______ End else if @opostrng like '_//'

end -- else of "if ( @opo2 = '/' ) and ( len ( replace(@opostrng,'/','') ) =2 )"

end -- if charindex( '/', @opostrng ) > 0.5

-- __________________ End process X @opo2 Y _____________________


end
-- goto mout2
-- I am (()) this helps to navigate around the code
-- End if @patern = '((non)o(non))' --______________________________________________


-- (no((non)on))
if @patern = '(no((non)on))' --____________________________________________________ begin

--I am (nn)) this helps to navigate around the code

-- Processing '(n1 op1 ((n2 op2 n3) op3 n4))' -----------
-- set numerator and denominator as required at each step
-- processing (n2 op2 n3)
set @numerator_n38 = @num2_int set @denominator_n38 = 1
-- __________________ process @num2_int @opo2 and @num3_int _____________________
if @opo2 = '/' set @denominator_n38 = @denominator_n38 * @num3_int else if @opo2 = '-' set @numerator_n38 = @numerator_n38 - @num3_int else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @num3_int else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + @num3_int

-- _________________ End process @num2_int @opo2 and @num3int ___________________


-- Processing '(n1 op1 ((n2 op2 n3) op3 n4))' -- ------
-- processing (X op3 n4)
if @denominator_n38 >= 1 and @denominator_n38 < 1.000000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - @num4_int else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + @num4_int end
else begin
-- @denominator_n38 denominator is changed, so perform altered processing

-- oporators @opo3 = '/' or @opo3 = '*' are not affected so process as normal
if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int
-- oporators @opo3 = '-' or @opo3 = '+' must multiply by denominator before adding or subtracting
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - (@num4_int *@denominator_n38 )
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + (@num4_int *@denominator_n38 )
end
-- ____________ End process @opo3 and @num4_int (X op3 n4) ________________


-- __________________ process X @opo2 Y _____________________
set @where = 0
-- Processing '(n1 op1 ((n2 op2 n3) op3 n4))'

--set @where = 1

if @denominator_n38 >=1 and @denominator_n38 < 1.00000000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo1 = '/' set @denominator_n38 = @num1_int * @denominator_n38 else if @opo1 = '-' set @numerator_n38 = @num1_int - @numerator_n38 else if @opo1 = '*' set @numerator_n38 = @num1_int * @numerator_n38 else if @opo1 = '+' set @numerator_n38 = @num1_int + @numerator_n38
-- This is for @opostrng = /?? where ? is any of '* + -'. -- When @opostrng like '/[*+-][*+-]' -- or, when (@opo1 = '/') and (@opo2 <> '/') and (@opo3 <> '/')
-- we are looking for n1/( n2 ? n3 ? n4 ) where ? is any of * + -. -- At this point @numerator_n38 = n2 ? n3 ? n4 and @denominator_n38 = n1. -- We want n1/( n2 ? n3 ? n4 ) , so we have to swap/ the two values in N -- and D as below.
-- if (@opo1 = '/') and (@opo2 <> '/') and (@opo3 <> '/')
if @opostrng like '/[*+-][*+-]' begin
set @ret1 = 'in /[*+-][*+-]' set @temp_holder_n38 = @numerator_n38 set @numerator_n38 = @denominator_n38 set @denominator_n38 = @temp_holder_n38 end
end -- if @opostrng like '/[*+-][*+-]'

else -- @denominator_n38 <> 1
begin
-- @denominator_n38 denominator is changed, so perform altered processing
-- oporators @opo1 = '/' or @opo1 = '*' are not affected so process as -- normal
if @opo1 = '/' set @denominator_n38 = @num1_int * @denominator_n38 else if @opo1 = '*' set @numerator_n38 = @num1_int * @numerator_n38
-- oporators @opo1 = '-' or @opo1 = '+' must multiply by denominator before -- adding or subtracting
else if @opo1 = '-' set @numerator_n38 = (@denominator_n38 * @num1_int) - @numerator_n38
else if @opo1 = '+' set @numerator_n38 = (@denominator_n38 * @num1_int) + @numerator_n38

-- When @opostrng = /// or @opostrng = //* -- n1/ (n2/(n3*n4)) == n1*(n3*n4)/n2 == ( n1*n3*n4)/n2 -- 1st n2/n3 == N=n2, D=n3, then n2/(n3*n4) == N=n2, D=n3*n4 -- then n1/(n2/(n3*n4)) == (n1*n3*n4)/n2 == N=n2, D=n1*n3*n4. -- However from the 1st line we want ( n1*n3*n4)/n2. So we have -- to swap values of N and D as below.
-- Also for @opostrng = //* -- n1/(n2*n4)/n3 == n1*n3/(n2*n4) N = (n2*n4) D = n1*n3 -- So, once again, we have to swap N and D
-- Also When @opostrng = '//?', where ? is either of '+ -' -- n1/ (n2 ? n3*n4)/n3 == n1*n3/(n2 ? n3*n4), so we need N=n1*n3, D=(n2 ? n3*n4) -- 1st n2/n3 == N=n2, D=n3, then (n2 ? n3*n4)/n3, so N=(n2 ? n3*n4), D=n3 -- then we want n1/((n2 ? n3*n4)/n3 ). However, the above processing gives us -- N=(n2 ? n3*n4) and D=n3*n1. -- However from the 2nd line above line we want N=n1*n3, D=(n2 ? n3*n4). So, once -- again, we have to swap values of N and D as below.
if @opostrng like '//_' -- where _ is any of '+ - * /' begin
set @ret1 = 'in //_ ' set @temp_holder_n38 = @numerator_n38 set @numerator_n38 = @denominator_n38 set @denominator_n38 = @temp_holder_n38 end

-- e.g. (958577566/((94447-966783884)/785)) -- Expression steps are below -- 1. (b-c) 2. ((b-c)/d) 3. a/((b-c)/d) == a*d/(b-c) -- Code actions are below -- 1. N = (b-c) D = 1 , 2. N = (b-c) D = d , 3. N = (b-c) D = a*d -- So, once again, we have to swop N and D
else if @opostrng like '/_/' -- where _ is any of '+ - * /' begin
set @ret1 = 'in /_/ ' set @temp_holder_n38 = @numerator_n38 set @numerator_n38 = @denominator_n38 set @denominator_n38 = @temp_holder_n38 end

end
-- if @opostrng = '///'
end


-- __________________ End process X @opo2 Y _____________________

-- I am (nn)) this helps to navigate around the code
-- End if @patern = '(no((non)on))' --______________________________________________


if not (@denominator_n38 >=1 and @denominator_n38 < 1.000000000000001)
-- The mod function 'x%y' appears to give starange results when -- negative numbers are involved (the results given are the reverse -- of my calculator), I have decided to take direct control.
-- if both D and R are the same sign there is no need for any action
if ( (@numerator_n38 <0) and (@denominator_n38 >0) ) or ( (@numerator_n38 >0) and (@denominator_n38 <0) ) begin
set @sign = '-' set @numerator_n38 = abs(@numerator_n38) set @denominator_n38 = abs(@denominator_n38)
end else if ( (@numerator_n38 <0) and (@denominator_n38 <0) ) begin
set @numerator_n38 = abs(@numerator_n38) set @denominator_n38 = abs(@denominator_n38)
end -- if both D and R are the same sign there is no need for action

-- if NOT (@denominator_n38 >=1 and @denominator_n38 < 1.000000000000001

if @denominator_n38 >=1 and @denominator_n38 < 1.000000000000001 set @ret2 = @sign+cast( @numerator_n38 as varchar(36) ) else begin
set @remndr_n3820 = @numerator_n38 % @denominator_n38 set @numerator_n38 = @numerator_n38 - @remndr_n3820

-- the value of numerator @numerator_n38 , is now an exact multiple of the -- denominator @denominator_n38 , so we can perform integer division to -- get the integer part of the result
set @numerator_n38 = @numerator_n38/@denominator_n38
-- if the decimal part is effectively 0 then report the integer part only, -- otherwise determine the decimal part
-- although there are 4 numbers with up to 9 digits each, in practice the -- remainder will always fit into a numeric(38,20)

if abs( @remndr_n3820 / @denominator_n38 ) < 0.00000000000000000001 set @ret2 = @sign+cast( @numerator_n38 as varchar(36) ) else
if @numerator_n38 <> 0
set @ret2 = concat( @sign , cast( @numerator_n38 as varchar(36) ) , cast( format( @remndr_n3820 / @denominator_n38 ,'.########################' ) as varchar(40) ) )
else
set @ret2 = concat( @sign, cast ( format ( @remndr_n3820 / @denominator_n38,'0.########################') as varchar(40) ) )
end -- if abs( @remndr_n3820 / @denominator_n38 ) < 0.00000000000000000001

RETURN (@ret2)
end

```
Due to the bizarre limitation of Microsoft that you can't use EXEC or SP_EXECUTESQL in a stored function. ( at least give us a read only version please) I have had to resort to the following type of code which, I have only just finished. Maybe you could find something useful within. I get error 'Body is limited to 30000 characters; you entered 41027. So have had delete the last two of the five main modules.
Retained are : '(((non)on)on)', '((non)o(non))', '(no((non)on))'.
Dropped are : '((no(non))on)','(no(no(non)))'.
```
create or ALTER FUNCTION [dbo].[mthscnvrt10](@strng varchar(60)) RETURNS varchar(220) AS BEGIN
/*
This function takes in a numeric string from a varchar column and translates it to its numeric value.
In this data, the numeric strings always have 4 numbers, which are all integers, and three arithmetic operators.
All numeric string calculations pair two numbers within parantheses. E.g. '(((622788*57)*101)/1009)' or '(622788/((1009/57)/101))' etc... Which you, the eagle eyed observer might have noticesd are actually equivalent.
The value of @patern governs which section of code is executed.
This data which this function is designed to process, has only the 5 @patern values listed below, so that is all I have coded for.
'(((non)on)on)' '((non)o(non))' '(no((non)on))' '((no(non))on)' '(no(no(non)))'
The @patern symbols '(' and ')' control order of execution. The n's represent the 4 numbers, num1, num2, num3 and num4 from left to right. The o's represent the arithmetic operators, opo1, opo2 and opo3 from left to right.
We are only interested in the general form of @patern, not the details, so the 'replace' code below reduces @patern strings like '(((nnnnnnonn)onnn)onnnn)' or '(nnnnnno((nnnnonn)onnnn))' to the basic form: '(((non)on)on)' or (no((non)on)) etc.
*/

declare @ret1 varchar(20)
declare @ret2 varchar(180)
declare @ret3 varchar(100)
declare @where smallint
DECLARE @dbg smallint
-- set @dbg= substring(@strng,1,1)
DECLARE @opo1 varchar(1) set @opo1='x'
DECLARE @opo2 varchar(1) set @opo2='x'
DECLARE @opo3 varchar(1) set @opo3='x'
DECLARE @opostrng varchar(3)
declare @num1_int int

declare @num1char varchar(10)
declare @num1cwnt smallint
set @num1char = '|'
set @num1cwnt = -1
set @num1_int = 0
declare @num2_int int
declare @num2char varchar(10)
declare @num2cwnt smallint
set @num2char = '|'
set @num2cwnt = -1

declare @num3_int int
declare @num3char varchar(10)
declare @num3cwnt smallint
set @num3char = '|'
set @num3cwnt = -1
declare @num4_int int
declare @num4char varchar(10)
declare @num4cwnt smallint
set @num4char = '|'
set @num4cwnt = -1
-- sql error line 7 !!!!!!!!!!
declare @sign varchar(1)
set @sign = ' '
declare @numerator_n38 numeric(38,0)
declare @denominator_n38 numeric(38,0)
declare @numerator_b_n38 numeric(38,0)
declare @denominator_b_n38 numeric(38,0)
declare @temp_holder_n38 numeric(38,0)
declare @division_n3820 numeric(38,20)
declare @division_b_n3820 numeric(38,20)
declare @dcmlpart_n3837 numeric(38,37)
declare @remndr_n3820 numeric(38,20)
declare @remndr_len_smallint smallint
declare @my_bigint bigint
declare @curval varchar(1)
declare @prevval varchar(1)
declare @mathstrng varchar(60)
declare @loopval smallint set @loopval=2
declare @strnglen smallint
declare @patern varchar(60)
declare @numflag smallint set @numflag=0

set @patern='('
set @prevval='('
--set @mathstrng =substring(@strng,2,59)
set @mathstrng =@strng
set @strnglen = len(@mathstrng)

-- This is the while loop which parses the pattern of the string -- -- @loopval begins at 2 because we know first char is always a '('

while @loopval <= @strnglen begin

-- gets each character from the string, 1 by 1
set @curval = substring(@mathstrng,@loopval,1)


if @curval = '(' or @curval = ')' begin set @patern=@patern+@curval end

-- constructs each of the arithmetic operators.
if @curval in ( '/','+','-','*') begin

-- builds the general pattern of the arithemetic expression
set @patern=@patern +'o'

-- begins construction of each of the arithmetic operators.
if @opo1='x' begin set @opo1 = @curval end
else if @opo2='x' begin set @opo2 = @curval end
else if @opo3='x' begin set @opo3 = @curval end
end -- if @opo1='x'
-- ends construction of each of the arithmetic operators.

-- below if block processes the 4 numeric stings
if @curval between '0' and '9' begin

-- builds the general pattern of the arithemetic expression
set @patern=@patern+'n'


-- below if block indicates which of the 4 number stings to process
if @num1cwnt = -1 begin set @numflag=1 -- set @num1cwnt=@loopval end
else if @num2cwnt = -1 and (@prevval not between '0' and '9') begin set @numflag=2 -- set @num2cwnt=@loopval end
else if @num3cwnt = -1 and (@prevval not between '0' and '9') begin set @numflag=3 -- set @num3cwnt=@loopval end
else if @num4cwnt = -1 and (@prevval not between '0' and '9') begin set @numflag=4 -- set @num4cwnt=@loopval end
-- End of block indicating which of the 4 number stings to process



-- begin if block indicates which of the 4 number stings we are constructing
if @numflag=1 begin set @num1char=@num1char+@curval end
else if @numflag=2 begin set @num2char=@num2char+@curval end
else if @numflag=3 begin set @num3char=@num3char+@curval end
else if @numflag=4 begin set @num4char=@num4char+@curval end
-- end if block indicating which of the 4 number stings we are constructing

end -- End if block processing the 4 numeric stings


-- keeps track of current, next and previous characters
set @loopval=@loopval+1 set @prevval = @curval

end
-- End of main while @loopval <= @strnglen


-- parsing is now complete
/* We are only interested in the general form of @patern, not the details, so the 'replace' code below reduces @patern strings like '(((nnnnnnonn)onnn)onnnn)' or '(nnnnnno((nnnnonn)onnnn))' to the basic form: '(((non)on)on)' or (no((non)on)) etc. */
set @patern = replace(@patern,'nnnnnnnnn','n') set @patern = replace(@patern,'nnnnnnnn','n') set @patern = replace(@patern,'nnnnnnn','n') set @patern = replace(@patern,'nnnnnn','n') set @patern = replace(@patern,'nnnnn','n') set @patern = replace(@patern,'nnnn','n') set @patern = replace(@patern,'nnn','n') set @patern = replace(@patern,'nn','n')

-- create each numeric value from its string value
set @num1_int = convert (int,substring(@num1char,2,9)) set @num2_int = convert (int,substring(@num2char,2,9)) set @num3_int = convert (int,substring(@num3char,2,9)) set @num4_int = convert (int,substring(@num4char,2,9))


-- the variable @opostrng helps to indicate which code to execute
set @opostrng=@opo1+@opo2+@opo3
--set @ret2 = @patern --@num1char+@num2char+@num3char+@num4char --goto mout

--set @ret2 = @patern --goto mout2
if @patern = '(((non)on)on)' --____________________________________________________ begin

--I am ((() this helps to navigate around the code

--set @ret2 = 'went into (((non)on)on)' --goto mout

-- this code processes expresssions of the form '(((n1 op1 n2) op2 n3) op3 n4)'
-- set numerator and denominator as required at each step
-- 1st performing (n1 op1 n2)

set @numerator_n38 = @num1_int
set @denominator_n38 = 1
-- __________________ process @opo1 and @num2_int _____________________
if @opo1 = '/' set @denominator_n38 = @denominator_n38 * @num2_int else if @opo1 = '-' set @numerator_n38 = @numerator_n38 - @num2_int else if @opo1 = '*' set @numerator_n38 = @numerator_n38 * @num2_int else if @opo1 = '+' set @numerator_n38 = @numerator_n38 + @num2_int
-- _________________ End process @opo1 and @num2_int ___________________


-- ___________________ process @opo2 and @num3_int _____________________

-- 2nd performing (X op2 n3)

if @denominator_n38 < 1.00000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo2 = '/' set @denominator_n38 = @denominator_n38 * @num3_int else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @num3_int else if @opo2 = '-' set @numerator_n38 = @numerator_n38 - @num3_int else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + @num3_int end
else begin
-- @denominator_n38 denominator is changed, so perform altered processing

-- operators @opo2 = '/' or @opo2 = '*' are not affected so process as normal
if @opo2 = '/' set @denominator_n38 = @denominator_n38 * @num3_int else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @num3_int
-- operators @opo2 = '-' or @opo2 = '+' must multiply by denominator before adding or subtracting
else if @opo2 = '-' set @numerator_n38 = @numerator_n38 - (@num3_int *@denominator_n38 ) else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + (@num3_int *@denominator_n38 )
end
-- ____________ End process @opo2 and @num3_int ________________


-- ______________ process @opo3 and @num4_int ___________________

-- 3rd performing (X op3 n4)
if @denominator_n38 < 1.000000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + @num4_int end

else begin
-- @denominator_n38 denominator is changed, so perform altered processing
-- operators @opo3 = '/' or @opo3 = '*' are not affected so process as normal
if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int



-- operators @opo3 = '-' or @opo3 = '+' must multiply by denominator before -- adding or subtracting
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - (@denominator_n38 * @num4_int) else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + (@denominator_n38 * @num4_int)

end
end

--____________ End process @opo3 and @num4_int ____________________
-- I am ((() this helps to navigate around the code

-- End if @patern = '(((non)on)on)' --______________________________________________


/* a/b / c/d = x/ c/d = xd/c = ad/bc ? 1/2 / 3/4 = 1.4/2.3 = 4/6 correct - so what ???
n1/n2 / n3/n4 == n1*n4 / n2*n3
or num/denom / num2/denom2 == num* denom2/ denom*num2
*/
-- ((non)o(non))
if @patern = '((non)o(non))' --____________________________________________________ begin

--I am (()) this helps to navigate around the code

-- Processing '((n1 op1 n2) op2 (n3 op3 n4)'
-- set numerator and denominator as required at each step
-- processing (n1 op1 n2)
set @numerator_n38 = @num1_int set @denominator_n38 = 1
-- __________________ process @num1_int @opo1 and @num2_int _____________________
if @opo1 = '/' set @denominator_n38 = @denominator_n38 * @num2_int else if @opo1 = '-' set @numerator_n38 = @numerator_n38 - @num2_int else if @opo1 = '*' set @numerator_n38 = @numerator_n38 * @num2_int else if @opo1 = '+' set @numerator_n38 = @numerator_n38 + @num2_int
-- REGARD THIS RESULT AS X
-- _________________ End process @num1_int @opo1 and @num2_int ___________________


-- processing (n3 op3 n4)
set @numerator_b_n38 = @num3_int set @denominator_b_n38 = 1
-- __________________ process @num3_int @opo3 and @num4_int _____________________
if @opo3 = '/' set @denominator_b_n38 = @denominator_b_n38 * @num4_int else if @opo3 = '-' set @numerator_b_n38 = @numerator_b_n38 - @num4_int else if @opo3 = '*' set @numerator_b_n38 = @numerator_b_n38 * @num4_int else if @opo3 = '+' set @numerator_b_n38 = @numerator_b_n38 + @num4_int
-- REGARD THIS RESULT AS Y
-- _________________ End process @num3_int @opo3 and @num4_int ___________________

-- __________________ process X @opo2 Y _____________________
set @where = 0
-- processes expressions with no '/' operators
if charindex( '/', @opostrng ) < 0.5 begin
--set @where = 1
if @opo2 = '-' set @numerator_n38 = @numerator_n38 - @numerator_b_n38 else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @numerator_b_n38 else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + @numerator_b_n38
end
-- processes expressions with at least one '/' operator
else if charindex( '/', @opostrng ) > 0.5 begin

-- processes expressions with only one central '/' operator. it does this by -- collapsing '/' characters within the 3 character string @opostrng, and then -- looking for a stringlength of two.
-- e.g. ((x-x)/(x+x)) , ((x*x)/(x+x)) etc
if ( @opo2 = '/' ) and ( len ( replace(@opostrng,'/','') ) =2 ) begin
-- n1-n2 / n3-n4 == num / num_b -- n1-n2 / n3+n4 == num / num_b -- n1*n2 / n3+n4 == num / num_b -- etc etc
set @where = 1
-- the denominator value is held in @numerator_b_n38 from above, but it has -- to be explicitly set here; the division is processed further along in this -- code (see below, near end)
set @denominator_n38 = @numerator_b_n38
end -- if ( @opo2 = '/' ) and ( len ( replace(@opostrng,'/','') ) =2 )
else begin
-- below processes expressions with one or more '/' operator.
set @numerator_n38 = @num1_int set @denominator_n38 = @num2_int set @numerator_b_n38 = @num3_int set @denominator_b_n38 = @num4_int

if @opostrng like '//_' begin
-- n1 / n2 / n3 ? n4 == num/denom / num_b ? denom_b

-- '///'
if @opo3 = '/' begin
-- n1/n2 / n3/n4 == num/denom / num_b/denom_b == num*denom_b / denom*num_b
-- this rearrangement significantly increases accuracy
set @numerator_n38 = @numerator_n38 * @denominator_b_n38 set @denominator_n38 = @denominator_n38 * @numerator_b_n38
end
-- '//*'
else if @opo3 = '*' set @denominator_n38 = ( @denominator_n38 * @numerator_b_n38 * @denominator_b_n38 )
-- '//-'
else if @opo3 = '-' set @denominator_n38 = ( @denominator_n38 * (@numerator_b_n38 - @denominator_b_n38) )
-- '//+'
else if @opo3 = '+' set @denominator_n38 = ( @denominator_n38 * (@numerator_b_n38 + @denominator_b_n38) )
end
-- ________________ End if @opostrng like '//_'

else if @opostrng like '/*_' begin
-- n1/n2 * n3/n4 == num/denom * num_b/denom_b == n1*n3/(n2*n4) -- == num*num_b / (denom*denom_b)
-- '/*/'
if @opo3 = '/' begin
set @numerator_n38 = @numerator_n38 * @numerator_b_n38 set @denominator_n38 = @denominator_n38 * @denominator_b_n38
end
-- n1/n2 * n3*n4 == num/denom * num_b*denom_b == (n1*n3*n4) /n2 -- == (num * num_b * denom_b)/denom
-- '/**'
else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @numerator_b_n38 * @denominator_b_n38
-- '/*-'
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 * (@numerator_b_n38 - @denominator_b_n38)
-- '/*+'
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 * (@numerator_b_n38 + @denominator_b_n38)
-- @denominator_n38 is already initialised
end
-- ________________ End else if @opostrng like '/*_'



else if @opostrng like '/+_' begin
-- n1/n2 + n3/n4 == num/denom + num_b/denom_b == ( n1*n4 + n2*n3 ) / (n2*n4) -- == ( (num-denom_b) + denom*num_b) ) / ( denom * denom_b )
-- '/+/'
if @opo3 = '/' begin
set @numerator_n38 = @numerator_n38 * @denominator_b_n38 set @numerator_n38 = @numerator_n38 + ( @denominator_n38 * @numerator_b_n38 )
set @denominator_n38 = @denominator_n38 * @denominator_b_n38
end
-- '/+*'
else if @opo3 = '*' set @numerator_n38 = @numerator_n38 + ( @denominator_n38 * @numerator_b_n38 * @denominator_b_n38 )
-- '/+-'
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 + ( @denominator_n38 *( @numerator_b_n38 - @denominator_b_n38 ) )
-- '/++'
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + ( @denominator_n38 *( @numerator_b_n38 + @denominator_b_n38 ) )
-- @denominator_n38 is already set correctly at initialisation
end
-- ________________ End else if @opostrng = '/+_'
else if @opostrng like '/-_' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b -- '/-?' == num - (numb * denom) / denom
-- '/-/'
if @opo3 = '/' begin
-- n1/n2 - n3/n4 == num/denom - num_b/denom_b == ( n1*n4 - n2*n3 ) / (n2*n4) -- == ( num*denom_b - denom*num_b ) )/ denom*denom_b
set @numerator_n38 = @numerator_n38 * @denominator_b_n38 set @numerator_n38 = @numerator_n38 - ( @denominator_n38 * @numerator_b_n38 ) set @denominator_n38 = @denominator_n38 * @denominator_b_n38
end
-- '/-*'
else if @opo3 = '*' set @numerator_n38 = @numerator_n38 - ( @denominator_n38 * @numerator_b_n38 * @denominator_b_n38 )
-- '/--'
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - ( @denominator_n38 *( @numerator_b_n38 - @denominator_b_n38 ) )
-- '/-+'
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 - ( @denominator_n38 *( @numerator_b_n38 + @denominator_b_n38 ) )
-- @denominator_n38 is already set correctly at initialisation
end
-- ________________ End else if @opostrng = '/-_'

else if @opostrng like '_-/' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b -- '/-?' == num - (numb * denom) / denom
-- a*b - c/d == (a*b*d )- c /d
-- '*-/'
if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @denominator_b_n38 ) - @numerator_b_n38
-- '--/'
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @denominator_b_n38 ) - @numerator_b_n38
-- '+-/'
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @denominator_b_n38 ) - @numerator_b_n38
set @denominator_n38 = @denominator_b_n38
end
-- ________________ End else if @opostrng like '_-/
else if @opostrng like '_+/' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b

if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @denominator_b_n38 ) + @numerator_b_n38
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @denominator_b_n38 ) + @numerator_b_n38
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @denominator_b_n38 ) + @numerator_b_n38
set @denominator_n38 = @denominator_b_n38

end
-- ________________ End else if @opostrng like '_+/'
else if @opostrng like '_*/' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b

if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @numerator_b_n38 )
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @numerator_b_n38 )
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @numerator_b_n38 )
set @denominator_n38 = @denominator_b_n38

end
-- ________________ End else if @opostrng like '_*/'

else if @opostrng like '_//' begin
-- n1-n2 / n3/n4 == num-denom / num_b/denom_b == ( n1-n2 / n3/n4 ) / (n2*n4) -- == ( (num-denom) * denom_b) / num_b
if @opo1 = '*' set @numerator_n38 = ( @numerator_n38 * @denominator_n38 * @denominator_b_n38 )
if @opo1 = '-' set @numerator_n38 = ( (@numerator_n38 - @denominator_n38 ) * @denominator_b_n38 )
if @opo1 = '+' set @numerator_n38 = ( (@numerator_n38 + @denominator_n38 ) * @denominator_b_n38 )
set @denominator_n38 = @numerator_b_n38
end -- _______ End else if @opostrng like '_//'

end -- else of "if ( @opo2 = '/' ) and ( len ( replace(@opostrng,'/','') ) =2 )"

end -- if charindex( '/', @opostrng ) > 0.5

-- __________________ End process X @opo2 Y _____________________


end
-- goto mout2
-- I am (()) this helps to navigate around the code
-- End if @patern = '((non)o(non))' --______________________________________________


-- (no((non)on))
if @patern = '(no((non)on))' --____________________________________________________ begin

--I am (nn)) this helps to navigate around the code

-- Processing '(n1 op1 ((n2 op2 n3) op3 n4))' -----------
-- set numerator and denominator as required at each step
-- processing (n2 op2 n3)
set @numerator_n38 = @num2_int set @denominator_n38 = 1
-- __________________ process @num2_int @opo2 and @num3_int _____________________
if @opo2 = '/' set @denominator_n38 = @denominator_n38 * @num3_int else if @opo2 = '-' set @numerator_n38 = @numerator_n38 - @num3_int else if @opo2 = '*' set @numerator_n38 = @numerator_n38 * @num3_int else if @opo2 = '+' set @numerator_n38 = @numerator_n38 + @num3_int

-- _________________ End process @num2_int @opo2 and @num3int ___________________


-- Processing '(n1 op1 ((n2 op2 n3) op3 n4))' -- ------
-- processing (X op3 n4)
if @denominator_n38 >= 1 and @denominator_n38 < 1.000000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - @num4_int else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + @num4_int end
else begin
-- @denominator_n38 denominator is changed, so perform altered processing

-- oporators @opo3 = '/' or @opo3 = '*' are not affected so process as normal
if @opo3 = '/' set @denominator_n38 = @denominator_n38 * @num4_int else if @opo3 = '*' set @numerator_n38 = @numerator_n38 * @num4_int
-- oporators @opo3 = '-' or @opo3 = '+' must multiply by denominator before adding or subtracting
else if @opo3 = '-' set @numerator_n38 = @numerator_n38 - (@num4_int *@denominator_n38 )
else if @opo3 = '+' set @numerator_n38 = @numerator_n38 + (@num4_int *@denominator_n38 )
end
-- ____________ End process @opo3 and @num4_int (X op3 n4) ________________


-- __________________ process X @opo2 Y _____________________
set @where = 0
-- Processing '(n1 op1 ((n2 op2 n3) op3 n4))'

--set @where = 1

if @denominator_n38 >=1 and @denominator_n38 < 1.00000000000000001
-- @denominator_n38 denominator is still 1, so perform normal processing
begin if @opo1 = '/' set @denominator_n38 = @num1_int * @denominator_n38 else if @opo1 = '-' set @numerator_n38 = @num1_int - @numerator_n38 else if @opo1 = '*' set @numerator_n38 = @num1_int * @numerator_n38 else if @opo1 = '+' set @numerator_n38 = @num1_int + @numerator_n38
-- This is for @opostrng = /?? where ? is any of '* + -'. -- When @opostrng like '/[*+-][*+-]' -- or, when (@opo1 = '/') and (@opo2 <> '/') and (@opo3 <> '/')
-- we are looking for n1/( n2 ? n3 ? n4 ) where ? is any of * + -. -- At this point @numerator_n38 = n2 ? n3 ? n4 and @denominator_n38 = n1. -- We want n1/( n2 ? n3 ? n4 ) , so we have to swap/ the two values in N -- and D as below.
-- if (@opo1 = '/') and (@opo2 <> '/') and (@opo3 <> '/')
if @opostrng like '/[*+-][*+-]' begin
set @ret1 = 'in /[*+-][*+-]' set @temp_holder_n38 = @numerator_n38 set @numerator_n38 = @denominator_n38 set @denominator_n38 = @temp_holder_n38 end
end -- if @opostrng like '/[*+-][*+-]'

else -- @denominator_n38 <> 1
begin
-- @denominator_n38 denominator is changed, so perform altered processing
-- oporators @opo1 = '/' or @opo1 = '*' are not affected so process as -- normal
if @opo1 = '/' set @denominator_n38 = @num1_int * @denominator_n38 else if @opo1 = '*' set @numerator_n38 = @num1_int * @numerator_n38
-- oporators @opo1 = '-' or @opo1 = '+' must multiply by denominator before -- adding or subtracting
else if @opo1 = '-' set @numerator_n38 = (@denominator_n38 * @num1_int) - @numerator_n38
else if @opo1 = '+' set @numerator_n38 = (@denominator_n38 * @num1_int) + @numerator_n38

-- When @opostrng = /// or @opostrng = //* -- n1/ (n2/(n3*n4)) == n1*(n3*n4)/n2 == ( n1*n3*n4)/n2 -- 1st n2/n3 == N=n2, D=n3, then n2/(n3*n4) == N=n2, D=n3*n4 -- then n1/(n2/(n3*n4)) == (n1*n3*n4)/n2 == N=n2, D=n1*n3*n4. -- However from the 1st line we want ( n1*n3*n4)/n2. So we have -- to swap values of N and D as below.
-- Also for @opostrng = //* -- n1/(n2*n4)/n3 == n1*n3/(n2*n4) N = (n2*n4) D = n1*n3 -- So, once again, we have to swap N and D
-- Also When @opostrng = '//?', where ? is either of '+ -' -- n1/ (n2 ? n3*n4)/n3 == n1*n3/(n2 ? n3*n4), so we need N=n1*n3, D=(n2 ? n3*n4) -- 1st n2/n3 == N=n2, D=n3, then (n2 ? n3*n4)/n3, so N=(n2 ? n3*n4), D=n3 -- then we want n1/((n2 ? n3*n4)/n3 ). However, the above processing gives us -- N=(n2 ? n3*n4) and D=n3*n1. -- However from the 2nd line above line we want N=n1*n3, D=(n2 ? n3*n4). So, once -- again, we have to swap values of N and D as below.
if @opostrng like '//_' -- where _ is any of '+ - * /' begin
set @ret1 = 'in //_ ' set @temp_holder_n38 = @numerator_n38 set @numerator_n38 = @denominator_n38 set @denominator_n38 = @temp_holder_n38 end

-- e.g. (958577566/((94447-966783884)/785)) -- Expression steps are below -- 1. (b-c) 2. ((b-c)/d) 3. a/((b-c)/d) == a*d/(b-c) -- Code actions are below -- 1. N = (b-c) D = 1 , 2. N = (b-c) D = d , 3. N = (b-c) D = a*d -- So, once again, we have to swop N and D
else if @opostrng like '/_/' -- where _ is any of '+ - * /' begin
set @ret1 = 'in /_/ ' set @temp_holder_n38 = @numerator_n38 set @numerator_n38 = @denominator_n38 set @denominator_n38 = @temp_holder_n38 end

end
-- if @opostrng = '///'
end


-- __________________ End process X @opo2 Y _____________________

-- I am (nn)) this helps to navigate around the code
-- End if @patern = '(no((non)on))' --______________________________________________



if not (@denominator_n38 >=1 and @denominator_n38 < 1.000000000000001)
-- The mod function 'x%y' appears to give starange results when -- negative numbers are involved (the results given are the reverse -- of my calculator), I have decided to take direct control.
-- if both D and R are the same sign there is no need for any action
if ( (@numerator_n38 <0) and (@denominator_n38 >0) ) or ( (@numerator_n38 >0) and (@denominator_n38 <0) ) begin
set @sign = '-' set @numerator_n38 = abs(@numerator_n38) set @denominator_n38 = abs(@denominator_n38)
end else if ( (@numerator_n38 <0) and (@denominator_n38 <0) ) begin
set @numerator_n38 = abs(@numerator_n38) set @denominator_n38 = abs(@denominator_n38)
end -- if both D and R are the same sign there is no need for action

-- if NOT (@denominator_n38 >=1 and @denominator_n38 < 1.000000000000001

if @denominator_n38 >=1 and @denominator_n38 < 1.000000000000001 set @ret2 = @sign+cast( @numerator_n38 as varchar(36) ) else begin
set @remndr_n3820 = @numerator_n38 % @denominator_n38 set @numerator_n38 = @numerator_n38 - @remndr_n3820

-- the value of numerator @numerator_n38 , is now an exact multiple of the -- denominator @denominator_n38 , so we can perform integer division to -- get the integer part of the result
set @numerator_n38 = @numerator_n38/@denominator_n38
-- if the decimal part is effectively 0 then report the integer part only, -- otherwise determine the decimal part
-- although there are 4 numbers with up to 9 digits each, in practice the -- remainder will always fit into a numeric(38,20)

if abs( @remndr_n3820 / @denominator_n38 ) < 0.00000000000000000001 set @ret2 = @sign+cast( @numerator_n38 as varchar(36) ) else
if @numerator_n38 <> 0
set @ret2 = concat( @sign , cast( @numerator_n38 as varchar(36) ) , cast( format( @remndr_n3820 / @denominator_n38 ,'.########################' ) as varchar(40) ) )
else
set @ret2 = concat( @sign, cast ( format ( @remndr_n3820 / @denominator_n38,'0.########################') as varchar(40) ) )
end -- if abs( @remndr_n3820 / @denominator_n38 ) < 0.00000000000000000001

RETURN (@ret2)
end

```

Needless to say, called in the usual ways.
select '((61677\*89972)\*79533)/3778)', \[dbo\].\[mthscnvrt10\]('(((61677\*89972)\*79533)/3778)')
select top 10 \*, \[dbo\].\[mthscnvrt10\](pict2) from Myaksessv2.dbo.npick4sv2

        
Present in both answers; Present only in the new answer; Present only in the old answer;