After thinking about it: A simple calculation like 100 * 0.1
would be nice in batch. So I made a first little work-around with acceptable results.
Maybe someone like to improve it with more steps and share it with the stack community as I do now. Or find some bugs.
My script atm is not so big and maybe integratable without adding to many lines.
It's only working with single type of operation. The script decide which one it is or if they are mixed up.
My method is to make integers of the calculation fetching the highest number of digits and fill up if necessary with ceros and (afterwards / before) remove redundant ceros.
@ECHO OFF
REM -> Seems to be a good approach to change directory to a safe folder...
SET "CurrentFolder=%CD%"
CD /D "%temp%"
SETLOCAL EnableExtensions EnableDelayedExpansion
ECHO/
SET CALC=10/2.5
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 4
ECHO/ Result: !Result!
ECHO/
SET CALC=2.5/000010
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 0.25
ECHO/ Result: !Result!
ECHO/
SET CALC=10/0.99
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 10.10101010101010101010101010101
ECHO/ Result: !Result!
ECHO/
SET CALC=0.7/0.38
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 1.8421052631578947368421052631579
ECHO/ Result: !Result!
ECHO/
SET CALC=15641/3.0810
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 5076.5985069782538136968516715352
ECHO/ Result: !Result!
ECHO/
SET CALC=5 / 0.0003
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 16666.666666666666666666666666667
ECHO/ Result: !Result!
ECHO/
SET CALC=1234*0.00008
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 0.09872
ECHO/ Result: !Result!
ECHO/
SET CALC=-515415+987165.001
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 471750.001
ECHO/ Result: !Result!
ECHO/
SET CALC=515415-515414.010
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 0.99
ECHO/ Result: !Result!
ECHO/
SET CALC=515415.09-515414.0001
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 1.0899
ECHO/ Result: !Result!
ECHO/
SET CALC=5415.09-5414.0001
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 1.0899
ECHO/ Result: !Result!
ECHO/
SET CALC=5415.09-15414.0001
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: -9998.9101
ECHO/ Result: !Result!
ECHO/
SET CALC=300 * 0.04
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 12
ECHO/ Result: !Result!
ECHO/
SET CALC=5414.09-5414.0001
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: 0.0899
ECHO/ Result: !Result!
ECHO/
ECHO -------------------------------------------------
ECHO Result * 105.3
ECHO -------------------------------------------------
SET CALC=!Result! * 105.3
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat Result "!CALC!"
ECHO/ Pre-Calc: ?
ECHO/ Result: !Result!
ECHO -------------------------------------------------
ECHO/
SET CALC=5414.09-5414.0001 * 42
ECHO/ Original: !CALC!
CALL :HandleFloat "%CALC%" CALCDEF DIGITS
ECHO/ DeFloated: !CALCDEF!
ECHO/ Digits: !DIGITS!
CALL :CalcFloat NoResult "!CALC!"
ECHO/ Pre-Calc: What was the question?
ECHO/ Result: !NoResult!
GOTO :EndOfBatch
REM -> CALL :CalcFloat OUTPUTVAR "Calculation" (PRECISION)
REM -> Allows calculations with floating point numbers. E.g.:
REM -> :CalcFloat OUTPUTVAR "7/2" 2 would set OUTPUTVAR to 3.5
REM -> You cannot mix multiplication or division with addition or subtraction (for now)!
REM <- Default value for PRECISION is 2.
REM -> 2147483647+1 = -2147483648 <-> 2147483647+2 = -2147483647 <-> 2147483647+3 = -2147483646 ...
:CalcFloat
IF "%~1" == "" EXIT /B 1
IF "%~2" == "" EXIT /B 1
CALL :HandleFloat "%~2" DeFloated NumDigits
SET /A CalcFloatPrecision=2
IF NOT "%~3" == "" (
SET /A CalcFloatPrecision=%~3
) ELSE IF "!NumDigits!" GEQ "4" (
SET /A CalcFloatPrecision=1
)
CALL :StrLen DeFloatedLen DeFloated
SET CalcFloatMode=
FOR /L %%I IN (0,1,%DeFloatedLen%) DO (
IF "!DeFloated:~%%I,1!" == "-" (
IF "!CalcFloatMode!" == "SCALE" GOTO :CalcFloatConfused
IF "!CalcFloatMode!" == "MULTI" GOTO :CalcFloatConfused
SET CalcFloatMode=BASIC
) ELSE IF "!DeFloated:~%%I,1!" == "+" (
IF "!CalcFloatMode!" == "SCALE" GOTO :CalcFloatConfused
IF "!CalcFloatMode!" == "MULTI" GOTO :CalcFloatConfused
SET CalcFloatMode=BASIC
) ELSE IF "!DeFloated:~%%I,1!" == "/" (
IF "!CalcFloatMode!" == "BASIC" GOTO :CalcFloatConfused
IF "!CalcFloatMode!" == "MULTI" GOTO :CalcFloatConfused
SET CalcFloatMode=SCALE
) ELSE IF "!DeFloated:~%%I,1!" == "*" (
IF "!CalcFloatMode!" == "BASIC" GOTO :CalcFloatConfused
IF "!CalcFloatMode!" == "SCALE" GOTO :CalcFloatConfused
SET CalcFloatMode=MULTI
)
)
IF NOT DEFINED CalcFloatMode SET CalcFloatMode=SCALE
IF "!CalcFloatMode!" == "BASIC" (
SET /A CalcFloatBaseResult=!DeFloated!
IF "%NumDigits%" GTR "0" (
CALL :StrLen CalcFloatBaseResultLen CalcFloatBaseResult
IF "!CalcFloatBaseResultLen!" LEQ "!NumDigits!" (
FOR /L %%i IN (1,1,%NumDigits%) DO IF "%%i" GEQ "!CalcFloatBaseResultLen!" SET CalcFloatBaseResult=0!CalcFloatBaseResult!
)
SET CalcFloatBaseResult=!CalcFloatBaseResult:~0,-%NumDigits%!.!CalcFloatBaseResult:~-%NumDigits%!
)
SET "%~1=!CalcFloatBaseResult!"
) ELSE IF "!CalcFloatMode!" == "MULTI" (
SET /A CalcFloatBaseResult=!DeFloated!
SET /A NumDigits=!NumDigits! * 2
IF "!NumDigits!" GTR "0" (
CALL :StrLen CalcFloatBaseResultLen CalcFloatBaseResult
IF !CalcFloatBaseResultLen! LSS !NumDigits! (
FOR /L %%i IN (0,1,!NumDigits!) DO IF !CalcFloatBaseResultLen! LEQ %%i SET CalcFloatBaseResult=0!CalcFloatBaseResult!
)
FOR /F "tokens=1" %%F IN ("!NumDigits!") DO SET CalcFloatBaseResult=!CalcFloatBaseResult:~0,-%%F!.!CalcFloatBaseResult:~-%%F!
)
SET "%~1=!CalcFloatBaseResult!"
) ELSE (
SET CalcFloatScale=1
SET CalcFloatVal=
FOR /L %%i IN (1,1,%CalcFloatPrecision%) DO SET /A CalcFloatScale*=10
SET /A CalcFloatVal=!CalcFloatScale! * !DeFloated!
SET /A CalcFloatVal1=!CalcFloatVal! / !CalcFloatScale!
SET /A CalcFloatVal2=!CalcFloatVal! - !CalcFloatVal1! * !CalcFloatScale!
SET "%~1=!CalcFloatVal1!.!CalcFloatVal2!"
)
CALL :StrLen FinalCalcLen %~1
FOR /L %%i IN (0,1,!FinalCalcLen!) DO IF "!%~1:~%%i,1!" == "." GOTO :CalcFloatRemoveCero
EXIT /B 0
:CalcFloatRemoveCero
SET /A FinalCalcLen=!FinalCalcLen! - 1
FOR /F "tokens=1" %%F IN ("!FinalCalcLen!") DO IF NOT "!%~1:~%%F,1!" == "." IF "!%~1:~%%F,1!" == "0" (
SET "%~1=!%~1:~0,-1!
GOTO :CalcFloatRemoveCero
)
IF "!%~1:~-1!" == "." SET "%~1=!%~1:~0,-1!
EXIT /B 0
:CalcFloatConfused
ECHO Well multiplication or division do not work together with addition or subtraction atm.
EXIT /B 1
REM -> CALL :HandleFloat "INPUT" OUTPUT (DIGITS)
REM -> Turns all floating numbers into integers.
REM <- INPUT: The calculation as sting.
REM <- OUTPUT: The variable which will hold the calculation without floating numbers.
REM <- DIGITS: Optional, the variable which will hold the number of maximum digits.
:HandleFloat
IF "%~2" == "" EXIT /B 1
SET "InputCalc=%~1"
IF "!InputCalc!" == "" EXIT /B 1
REM -> Stage I: Get the maximum digits.
CALL :StrLen InputCalcLen InputCalc
IF %InputCalcLen% EQU 0 EXIT /B
SET /A InputCalcNumberDigits=0
SET /A InputCalcNumberDigitsPrev=0
SET "InputCalc=!InputCalc!#"
FOR /L %%I IN (0,1,%InputCalcLen%) DO (
SET InputCalcCharIsPoint=FALSE
IF "!InputCalc:~%%I,1!" == "." (
SET InputCalcCharIsPoint=TRUE
) ELSE IF "!InputCalc:~%%I,1!" == "," (
SET InputCalcCharIsPoint=TRUE
)
IF "!InputCalcCharIsPoint!" == "TRUE" SET NumbersExpected=TRUE
SET InputCalcCharIsNum=FALSE
IF "!InputCalc:~%%I,1!" == "0" (
SET InputCalcCharIsNum=TRUE
) ELSE (
SET /A InputCalcCharIsNumTest=0
SET /A InputCalcCharIsNumTest=!InputCalc:~%%I,1! >NUL 2>&1
IF "!InputCalcCharIsNumTest!" GTR "0" SET InputCalcCharIsNum=TRUE
)
IF "!InputCalcCharIsNum!" == "TRUE" (
IF "!NumbersExpected!" == "TRUE" (
SET /A InputCalcNumberDigitsPrev=!InputCalcNumberDigitsPrev!+1
)
) ELSE (
IF "!InputCalcCharIsPoint!" == "FALSE" (
SET NumbersExpected=FALSE
IF "!InputCalcNumberDigitsPrev!" GTR "!InputCalcNumberDigits!" SET /A InputCalcNumberDigits=!InputCalcNumberDigitsPrev!
SET /A InputCalcNumberDigitsPrev=0
)
)
)
IF NOT "%~3" == "" SET "%~3=!InputCalcNumberDigits!"
REM -> Stage II: Adjust numbers.
IF !InputCalcNumberDigits! GTR 0 (
SET NewInputCalc=
SET NewInputCalcFloatPart=
SET InputCalcPrevCharWasNum=FALSE
SET RedudantCero=FALSE
FOR /L %%I IN (0,1,%InputCalcLen%) DO (
SET InputCalcCharIsPoint=FALSE
IF "!InputCalc:~%%I,1!" == "." (
SET InputCalcCharIsPoint=TRUE
) ELSE IF "!InputCalc:~%%I,1!" == "," (
SET InputCalcCharIsPoint=TRUE
)
IF "!InputCalcCharIsPoint!" == "TRUE" SET NumbersExpected=TRUE
SET InputCalcCharIsNum=FALSE
IF "!InputCalc:~%%I,1!" == "0" (
IF NOT "!NumbersExpected!" == "TRUE" (
IF NOT "!InputCalcPrevCharWasNum!" == "TRUE" (
SET RedudantCero=TRUE
SET InputCalcCharIsNum=FALSE
)
)
IF NOT "!RedudantCero!" == "TRUE" SET InputCalcCharIsNum=TRUE
) ELSE (
SET /A InputCalcCharIsNumTest=0
SET /A InputCalcCharIsNumTest=!InputCalc:~%%I,1! >NUL 2>&1
IF "!InputCalcCharIsNumTest!" GTR "0" SET InputCalcCharIsNum=TRUE
)
IF NOT "!RedudantCero!" == "TRUE" (
IF "!InputCalcCharIsNum!" == "TRUE" (
IF "!NumbersExpected!" == "TRUE" (
SET "NewInputCalcFloatPart=!NewInputCalcFloatPart!!InputCalc:~%%I,1!"
) ELSE (
SET "NewInputCalc=!NewInputCalc!!InputCalc:~%%I,1!"
)
) ELSE (
IF "!InputCalcCharIsPoint!" == "FALSE" (
SET NumbersExpected=FALSE
IF DEFINED NewInputCalcFloatPart (
SET /A NewInputCalcFloatPartIsCero=!NewInputCalcFloatPart! >NUL 2>&1
IF "!NewInputCalcFloatPartIsCero!" == "0" (
SET InputCalcPrevCharWasNum=TRUE
SET NewInputCalcFloatPart=
)
)
IF DEFINED NewInputCalcFloatPart (
CALL :HandleFloatBuildFloat NewInputCalc NewInputCalcFloatPart InputCalcNumberDigits
SET NewInputCalcFloatPart=
) ELSE IF "!InputCalcPrevCharWasNum!" == "TRUE" (
FOR /L %%I IN (1,1,!InputCalcNumberDigits!) DO SET "NewInputCalc=!NewInputCalc!0"
)
SET "NewInputCalc=!NewInputCalc!!InputCalc:~%%I,1!"
)
)
)
SET RedudantCero=FALSE
SET InputCalcPrevCharWasNum=!InputCalcCharIsNum!
)
CALL :StrLen NewInputCalcLen NewInputCalc
SET /A NewInputCalcLen=!NewInputCalcLen! - 1
FOR /F "tokens=1" %%F IN ("!NewInputCalcLen!") DO SET "%~2=!NewInputCalc:~0,%%F!"
) ELSE (
SET "%~2=%~1"
)
EXIT /B 0
:HandleFloatBuildFloat
CALL :StrLen NewInputCalcFloatPartLen %~2
SET NewInputCalcFloatPartRedudantCero=FALSE
SET /A CurrentNewInputCalcLen=0
IF "!%~2:~0,1!" == "0" (
IF "!%~1!" == "" SET NewInputCalcFloatPartRedudantCero=TRUE
IF "!NewInputCalcFloatPartRedudantCero!" == "FALSE" (
SET NewInputCalcCharIsNumTest=
SET /A NewInputCalcCharIsNumTest=!%~1:~-1! >NUL 2>&1
IF NOT DEFINED NewInputCalcCharIsNumTest SET NewInputCalcFloatPartRedudantCero=TRUE
)
IF "!NewInputCalcFloatPartRedudantCero!" == "FALSE" CALL :StrLen CurrentNewInputCalcLen NewInputCalc
)
:HandleFloatBuildFloatGetLastNonFloat
IF "!CurrentNewInputCalcLen!" GTR "0" (
SET /A CurrentNewInputCalcLen=!CurrentNewInputCalcLen! - 1
FOR /F "tokens=1" %%F IN ("!CurrentNewInputCalcLen!") DO (
IF "!%~1:~%%F,1!" GEQ "0" IF "!%~1:~%%F,1!" LEQ "9" (
SET NewInputCalcFloatPartRedudantCero=FALSE
IF "!%~1:~%%F,1!" == "0" SET NewInputCalcFloatPartRedudantCero=TRUE
GOTO :HandleFloatBuildFloatGetLastNonFloat
)
)
)
FOR /L %%I IN (0,1,!%~3!) DO (
SET SkipCurrentNumber=FALSE
IF "!NewInputCalcFloatPartRedudantCero!" == "TRUE" (
IF "!%~2:~%%I,1!" == "0" (
SET SkipCurrentNumber=TRUE
) ELSE (
SET NewInputCalcFloatPartRedudantCero=FALSE
)
)
IF "!SkipCurrentNumber!" == "FALSE" (
IF "%%I" GTR "!NewInputCalcFloatPartLen!" (
SET "%~1=!%~1!0"
) ELSE (
SET "%~1=!%~1!!%~2:~%%I,1!"
)
)
)
EXIT /B
REM -> CALL :StrLen CountVar StringVar
REM -> Sets CountVar var to the number of characters of the given StringVar
:StrLen
(
IF "%~1" == "" EXIT /B 1
(SET^ tmp=!%~2!)
IF DEFINED tmp (
SET /A "len=1"
FOR %%P IN (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) DO (
IF "!tmp:~%%P,1!" NEQ "" (
SET /A "len+=%%P"
SET "tmp=!tmp:~%%P!"
)
)
) ELSE (
SET /A "len=0"
)
SET /A "%~1=!len!"
EXIT /B 0
)
REM -> Resets
:EndOfBatch
ECHO.
ECHO Exiting batch now...
ECHO.
ping 1.2.3.4 -n 1 -w 200 >NUL
ENDLOCAL
CD /D "%CurrentFolder%"
ping 1.2.3.4 -n 1 -w 100 >NUL
GOTO :Exit
:Exit
Results:
Original: 10/2.5
DeFloated: 100/25
Digits: 1
Pre-Calc: 4
Result: 4
Original: 2.5/000010
DeFloated: 25/100
Digits: 1
Pre-Calc: 0.25
Result: 0.25
Original: 10/0.99
DeFloated: 1000/99
Digits: 2
Pre-Calc: 10.10101010101010101010101010101
Result: 10.1
Original: 0.7/0.38
DeFloated: 70/38
Digits: 2
Pre-Calc: 1.8421052631578947368421052631579
Result: 1.84
Original: 15641/3.0810
DeFloated: 156410000/30810
Digits: 4
Pre-Calc: 5076.5985069782538136968516715352
Result: 5076.5
Original: 5 / 0.0003
DeFloated: 50000 / 3
Digits: 4
Pre-Calc: 16666.666666666666666666666666667
Result: 16666.6
Original: 1234*0.00008
DeFloated: 123400000*8
Digits: 5
Pre-Calc: 0.09872
Result: 0.09872
Original: -515415+987165.001
DeFloated: -515415000+987165001
Digits: 3
Pre-Calc: 471750.001
Result: 471750.001
Original: 515415-515414.010
DeFloated: 515415000-515414010
Digits: 3
Pre-Calc: 0.99
Result: 0.99
Original: 515415.09-515414.0001
DeFloated: 5154150900-5154140001
Digits: 4
Invalid number. Numbers are limited to 32-bits of precision.
Pre-Calc: 1.0899
Result: 0..99
Original: 5415.09-5414.0001
DeFloated: 54150900-54140001
Digits: 4
Pre-Calc: 1.0899
Result: 1.0899
Original: 5415.09-15414.0001
DeFloated: 54150900-154140001
Digits: 4
Pre-Calc: -9998.9101
Result: -9998.9101
Original: 300 * 0.04
DeFloated: 30000 * 4
Digits: 2
Pre-Calc: 12
Result: 12
Original: 5414.09-5414.0001
DeFloated: 54140900-54140001
Digits: 4
Pre-Calc: 0.0899
Result: 0.0899
-------------------------------------------------
Result * 105.3
-------------------------------------------------
Original: 0.0899 * 105.3
DeFloated: 899 * 1053000
Digits: 4
Pre-Calc: ?
Result: 9.46647
-------------------------------------------------
Original: 5414.09-5414.0001 * 42
DeFloated: 54140900-54140001 * 420000
Digits: 4
Well multiplication or division do not work together with addition or subtraction atm.
Pre-Calc: What was the question?
Result:
%VAR:~0,-2%.%VAR:~-2%
?? β Elnoraelnore