Hello @javed,
It's a little bit hard without using any dotnet function. But there's also a workaround that you can try by creating a control add-in and using javascript code on-page. It's just a suggestion, I will try this to give you a better idea.
For calculating this kind of mathematical expression you need to think about all the symbols that you will gonna use while entering the expression after that you need to find which expression is going to execute first, based on the opening and closing brackets.
I can provide you a MathLib codeunit as given follows, given codeunit can do different mathematical calculation but can't able to solve an expression you need to look into, I will also confirm when I will come up with any solution:
codeunit 80005 MathLib
{
// Mathlib by René Thöne/Landefeld Druckluft GmbH Kassel rthsw@web.de.
// Uses free avaible Algorithmen from the last 300 Years.
// Please feel free to use and Modify, but for Fairness let my name in the Unit.
trigger OnRun()
begin
MESSAGE('Ln(20) = %1', Ln(20));
MESSAGE('Lg(7) = %1', Log(7));
MESSAGE('6! = %1', "!"(6));
MESSAGE('Sin(30) = %1', Sin("Grad>Rad"(30)));
MESSAGE('Cos(30) = %1', Cos("Grad>Rad"(30)));
MESSAGE('Tan(30) = %1', Tan("Grad>Rad"(30)));
MESSAGE('ArcSin(0.2) = %1', "Grad>Rad"(0.2));
MESSAGE('ArcCos(0.3) = %1', ArcCos("Grad>Rad"(0.3)));
MESSAGE('ArcTan(-5.8) = %1', ArcTan(-5.8));
MESSAGE('30° adjusted by PI = %1', Adjust(30));
MESSAGE('Squareroot of 30 = %1', Sqrt(30));
MESSAGE('the greatest common Divisor of 35 and 25 = %1', gcd(35, 25));
MESSAGE('the least common multipler of 35 and 25 = %1', lcm(35, 25));
MESSAGE('29 is %1 prime, 30 is %2 prime', Prime(29), Prime(30));
MESSAGE('the CrossFoot of 123 is %1', CrossFoot(123));
MESSAGE('PI = %1, Exp = %2, e (euler) = %3', Pi, E, Euler);
MESSAGE('the sign of -23 is %1, the sign of 45 is %2', Sign(-23), Sign(45));
MESSAGE('the max of 23 and 45 is %1', Max(23, 45));
MESSAGE('the min of 23 and 45 is %1', Min(23, 45));
MESSAGE('the Integer of 34,567 is %1', Int(34.567));
//the following Units are also working, but no examples given
//EuklDistance
//ManhDistance
//StreetDistance
//ConvLongtitute2Km
//ConvLatitude2Km
end;
var
VarName: array[99] of Code[20];
VarValue: array[99] of Decimal;
[Scope('Internal')]
procedure "!"(x: Decimal) "Fakultät": Decimal
begin
Fakultät := x;
WHILE x > 1 DO BEGIN
x -= 1;
Fakultät := Fakultät * x
END;
end;
[Scope('Internal')]
procedure Sin(x: Decimal): Decimal
begin
//Taylor works well, but differs in the near of 90°
//EXIT(
// x - (POWER(x,3)/"!"(3)) + (POWER(x,5)/"!"(5))
// - (POWER(x,7)/"!"(7)) + (POWER(x,9)/"!"(9))
// - (POWER(x,12)/"!"(11)));
//so better use Horner
EXIT(x * (1 - (x * x) * (1 - (x * x) * (1 - (x * x) * (1 - (x * x) * (1 - (x * x) * (1 - (x * x) * (1 - (x * x) * (1 - (x * x)
/ (16 * 17)) / (14 * 15)) / (12 * 13)) / (10 * 11)) / (8 * 9)) / (6 * 7)) / (4 * 5)) / (2 * 3)));
end;
[Scope('Internal')]
procedure Cos(x: Decimal) Cos: Decimal
begin
/*EXIT(
1 - (POWER(x,2)/"!"(2)) + (POWER(x,4)/"!"(4))
- (POWER(x,6)/"!"(6)) + (POWER(x,8)/"!"(8))
- (POWER(x,10)/"!"(10)));*/
//Taylor gives better result in normal areas, but Honer results better on extreme (0° 90°)
EXIT(Sin(x + Pi / 2));
end;
[Scope('Internal')]
procedure Tan(x: Decimal): Decimal
begin
EXIT(Sin(x) / Cos(x));
end;
[Scope('Internal')]
procedure ArcSin(x: Decimal) a: Decimal
begin
IF x < 0 THEN
EXIT(-ArcSin(-x))
ELSE
IF x = 1 THEN
EXIT(Pi / 2)
ELSE
EXIT(ArcTan(x / Sqrt(1 - x * x)));
end;
[Scope('Internal')]
procedure ArcCos(x: Decimal) a: Decimal
begin
IF x < 0 THEN
EXIT(Pi - ArcCos(-x))
ELSE
IF x = 0 THEN
EXIT(Pi / 2)
ELSE
EXIT(ArcTan(Sqrt(1 - x * x) / x));
end;
[Scope('Internal')]
procedure ArcTan(x: Decimal) ATan: Decimal
var
"Sum": Decimal;
i: Integer;
Inverting: Boolean;
begin
//Again, Taylor is our friend, but only from -1..1, the rest will be calculated by this.
Inverting := (x < -1) OR (x > 1);
IF Inverting THEN
x := 1 / x;
CLEAR(ATan);
FOR i := 1 TO 100 DO BEGIN
ATan += (POWER(x, i) / i) - (POWER(x, i + 2) / (i + 2));
i += 3;
END;
IF Inverting THEN
IF x > 0 THEN
EXIT(Pi / 2 - ATan)
ELSE
EXIT(-Pi / 2 - ATan)
end;
[Scope('Internal')]
procedure Log(x: Decimal): Decimal
begin
EXIT(CalcLog(10, x));
end;
[Scope('Internal')]
procedure Ln(x: Decimal): Decimal
begin
EXIT(CalcLog(E, x));
//You could also calculate Ln with Taylorrows. It's (depending on the Acuracy) faster than the Root.
//I preffer the Root-Algorythmus, because it is "smarter" and becomes allways maximal accurate.
//Taylor becommes on very low (< 0,5) and high (> 100) Values more unaccurate.
//IF (x <= 0) THEN
// ERROR('Ln out of Range (>0)');
//CLEAR(Sum);
//FOR i := 1 TO 40 DO BEGIN
// Sum := Sum + POWER(x-1,i) / (i * POWER(x+1,i));
// i += 1; //Step2
//END;
//For Ln (Base euler)->
//EXIT(2*Sum);
//For Log (Base 10)
//exit(x/2.30258509299);
end;
local procedure CalcLog(Base: Decimal; x: Decimal): Decimal
var
Down: Decimal;
Up: Decimal;
Step: Decimal;
Steps: Integer;
LeadingZeros: Integer;
LeadingZeroString: Text[30];
begin
CLEAR(Steps);
IF x = 1 THEN //Log(1) = 1;
EXIT(1);
//first find upper and lower Range
IF x > 1 THEN BEGIN
Up := 1;
Down := 0;
WHILE POWER(Base, Up) < x DO
Up *= 2;
Down := Up;
WHILE POWER(Base, Down) > x DO
Down /= 10;
END ELSE BEGIN
//On Values 0..1 (except 0) the leading zeros are the offset in -Integer
//i.e. 0,0027 leads to -2, because the LOG will be something between -2 and zero.
Down := -STRLEN(COPYSTR(FORMAT(x, 0, '<decimals,0>'), 2)) -
STRLEN(DELCHR(COPYSTR(FORMAT(x, 0, '<decimals,0>'), 2), '<', '0'));
Up := 0;
END;
//moving the Ranges step by step to the Result. Steps become smaler every loop.
REPEAT
Steps += 1;
Step := (Up - Down) / 2;
IF POWER(Base, Step + Down) > x THEN
Up -= Step
ELSE
Down += Step;
UNTIL Steps = 53; //after this Navision doesnt get exacter. The first 12-14 decimals are allways acurate.
EXIT(ROUND(Up, 0.000000000000001));
end;
[Scope('Internal')]
procedure Adjust(x: Decimal): Decimal
begin
REPEAT
IF x <= -Pi THEN
x := x + 2 * Pi;
IF x > Pi THEN
x := x - 2 * Pi
UNTIL (x > -Pi) AND (x <= Pi);
end;
[Scope('Internal')]
procedure "Grad>Rad"(Grad: Decimal) Rad: Decimal
begin
EXIT(Grad / 180 * Pi);
end;
[Scope('Internal')]
procedure "Deg>Rad"(x: Decimal): Decimal
begin
EXIT(x * (Pi / 180));
end;
[Scope('Internal')]
procedure "Rad>Deg"(x: Decimal): Decimal
begin
EXIT(x * (180 / Pi));
end;
[Scope('Internal')]
procedure Sqrt(x: Decimal): Decimal
begin
EXIT(POWER(x, 0.5));
end;
[Scope('Internal')]
procedure gcd(x: Decimal; y: Decimal): Decimal
var
Puffer: Decimal;
begin
//größter gemeinsamer Teiler
x := ABS(Int(x));
y := ABS(Int(y));
IF (x = 0) AND (y = 0) THEN
EXIT(0);
IF (x = 0) OR (x = y) THEN
EXIT(y);
IF y = 0 THEN
EXIT(x);
REPEAT
IF x < y THEN BEGIN
Puffer := x;
x := y;
y := Puffer;
END;
Puffer := x MOD y;
x := y;
y := Puffer;
UNTIL Puffer = 0;
EXIT(x);
end;
[Scope('Internal')]
procedure lcm(x: Decimal; y: Decimal): Decimal
begin
//kleinstes gemeinsames Vielfaches
x := ABS(Int(x));
y := ABS(Int(y));
EXIT(x * y DIV gcd(x, y));
end;
[Scope('Internal')]
procedure Prime(x: Decimal): Boolean
var
i: Integer;
begin
//Primzahl?
x := ABS(x);
IF x IN [0, 1] THEN
EXIT(FALSE);
IF x IN [2, 3] THEN
EXIT(TRUE);
i := 2;
WHILE i <= Int(Sqrt(x)) DO BEGIN
IF (x MOD i = 0) THEN
EXIT(FALSE);
i += 1;
END;
EXIT(TRUE);
end;
[Scope('Internal')]
procedure CrossFoot(x: Decimal): Decimal
begin
//Quersumme
x := ABS(Int(x));
EXIT((x - 10) MOD 9 + 1);
end;
[Scope('Internal')]
procedure "(a+b)²"(a: Decimal; b: Decimal): Decimal
begin
//Binomic1
EXIT(POWER(a, 2) + 2 * a * b + POWER(b, 2));
end;
[Scope('Internal')]
procedure "(a-b)²"(a: Decimal; b: Decimal): Decimal
begin
//Binomic2
EXIT(POWER(a, 2) - 2 * a * b + POWER(b, 2));
end;
[Scope('Internal')]
procedure "(a+b)*(a-b)"(a: Decimal; b: Decimal): Decimal
begin
//Binomic3
EXIT(POWER(a, 2) - POWER(b, 2));
end;
[Scope('Internal')]
procedure Pi(): Decimal
begin
EXIT(3.1415926535897932384626);
end;
[Scope('Internal')]
procedure E(): Decimal
begin
EXIT(2.7182818284590452353603);
end;
[Scope('Internal')]
procedure Euler(): Decimal
begin
EXIT(0.5772156649015328606065);
end;
[Scope('Internal')]
procedure Sign(x: Decimal): Integer
begin
IF x < 0 THEN
EXIT(-1);
IF x = 0 THEN
EXIT(0);
EXIT(1);
end;
[Scope('Internal')]
procedure "Max"(Dec1: Decimal; Dec2: Decimal): Decimal
begin
IF Dec1 > Dec2 THEN
EXIT(Dec1)
ELSE
EXIT(Dec2);
end;
[Scope('Internal')]
procedure "Min"(Dec1: Decimal; Dec2: Decimal): Decimal
begin
IF Dec1 > Dec2 THEN
EXIT(Dec2)
ELSE
EXIT(Dec1);
end;
[Scope('Internal')]
procedure Int(x: Decimal): Decimal
begin
EXIT(ROUND(x, 1, '<'));
end;
[Scope('Internal')]
procedure EuklDistance(x1: Decimal; y1: Decimal; x2: Decimal; y2: Decimal): Decimal
begin
EXIT(Sqrt(POWER((x2 - x1), 2) + POWER((y2 - y1), 2)));
end;
[Scope('Internal')]
procedure ManhDistance(x1: Decimal; y1: Decimal; x2: Decimal; y2: Decimal): Decimal
begin
EXIT(ABS(x2 - x1) + ABS(y2 - y1));
end;
[Scope('Internal')]
procedure StreetDistance(x1: Decimal; y1: Decimal; x2: Decimal; y2: Decimal): Decimal
begin
EXIT((ABS(x2 - x1) + ABS(y2 - y1)) * 1.111);
end;
[Scope('Internal')]
procedure ConvLongtitute2Km(Latitude: Decimal; x: Decimal): Decimal
var
Multiplier: Decimal;
begin
//Längengrad zu Km
EXIT(Cos("Grad>Rad"(Latitude)) * 111.32386667);
end;
[Scope('Internal')]
procedure ConvLatitude2Km(x: Decimal): Decimal
begin
//Breitengrad zu km
EXIT(x * 111.32386667);
end;
local procedure "---Parser---"()
begin
end;
[Scope('Internal')]
procedure Parse(String: Integer) result: Decimal
begin
InitParser;
end;
local procedure SetV(Name: Code[20]; Value: Decimal)
var
i: Integer;
TXTEmptyName: Label 'Empty Varname for Value %1';
FirstFreeVar: Integer;
TXT2MaxVars: Label 'Not enough room to store %1. Only 99 Vardefinitions are allowed.';
begin
IF Name = '' THEN
ERROR(TXTEmptyName);
CLEAR(FirstFreeVar);
FOR i := 1 TO 99 DO BEGIN
IF VarName[i] = Name THEN BEGIN
VarValue[i] := Value;
EXIT;
END;
IF VarName[i] = '' THEN BEGIN
FirstFreeVar := i;
i := 100;
END;
END;
IF FirstFreeVar = 0 THEN
ERROR(TXT2MaxVars, Name);
VarName[FirstFreeVar] := Name;
VarValue[FirstFreeVar] := Value;
end;
local procedure GetV(Name: Code[20]) Value: Decimal
var
i: Integer;
TXTunknownVar: Label 'Unknown Var: %1';
begin
FOR i := 1 TO 99 DO
IF VarName[i] = Name THEN
EXIT(VarValue[i]);
ERROR(TXTunknownVar, Name);
end;
local procedure InitParser()
begin
CLEAR(VarName);
CLEAR(VarValue);
end;
}
This MathLib codeunit doesn't contain a solution for your question but it's good to know what other MATH things we can do in Business Central