Basic BAT calculator command - batch-file

I am trying to do a very basic 2 value input BAT file but I am struggling. I used a free template from Wikihow and re-adjusted but something is not right.
I want to calculate 100/(A/B+1) and I know for a fact that the Batch calculation ignores the "+1" for some reason and basically just calculates "100/(A/B). Please help. Thanks.
TITLE Calculator
ECHO OFF
CLS
:TOP
color 3f
Cls
:SUM
CLS
ECHO ---------------------------------------------------
ECHO[
ECHO Division
ECHO[
ECHO ---------------------------------------------------
ECHO[
set /p A=" Enter First Amount = "
ECHO[
set /p B=" Enter Second Amount = "
SET /A C=100/(A/B+1)
ECHO[
ECHO ---------------------------------------------------
ECHO Result %C%
PAUSE
GOTO:TOP

I suspect this is an order of operations issue.
Remember that plus comes after division.
You might need this instead:
SET /A C=100/(A/(B+1))
This will allow the B+1 to come before the division.

SET /A doesn't ignore the +1:
E.g. SET /A 100/(10/2+1) outputs 16; the problem you most likely have is this:
Any SET /A calculation that returns a fractional result will be
rounded down to the nearest whole integer.
(Source)
However, it is possible to work around this issue:
SETLOCAL EnableDelayedExpansion
SET /A "var=100000/(10/2+1)"
SET "fraction=%var:~-3%" & SET /A "var/=1000"
IF !fraction:~-1! GEQ 5 SET /A "fraction+=10"
SET "fraction=!fraction:~0,-1!"
ECHO %var%.%fraction%
Basically you multiply the number to be divided by 10^(n) and - after you set the fraction (%var:~-n%) - divide it by 10^(n) again. Then you check the last digit of the fraction for proper rounding and remove it (read more).

I am assuming you were looking for:
SET /A C=(A/B)+1
SET /A C=100/(C)
This the correct formula, but it will not return the correct results for fractioned numbers.
So if A = 10 and B = 2
10 / 2 = 5 +1 =6
100/6 = 16,6 but batch rounds off to 16.
Then A = 453 and B = 178
453 / 178 = 2,544943820224719
2,544943820224719 + 1 = 3,544943820224719 but Batch rounds off to 3
100/3 = 33
So if you use numbers that will cause fractions, you MUST use a solution that include fractions.

Related

How can I make a random number/letter generator?

Hello guys I am very bad at notepad, I want to make a random code generator.
That Generates codes like this 3K2EU-ZGS5L-P3DNL-YM9JC
I want it to work with a notepad .bat file so I can let it run on my PC
This can be done using %random% values to assign numbers and letters as demonstrated
below. If you need letters and numbers in specific places within the 20 digits,
adjust the Condition used to call getLetters or Getnumber to call according to current
%dig%==number
#ECHO OFF
SETLOCAL enableDelayedExpansion
:open
Set dig=0
:main
Set /a dig=%dig% + 1
CALL :digit%dig%
Call LetorNum
IF %dig%==20 goto result
GOTO main
:LetorNum
Set /a pick=%random% * 2 / 32768 + 1
IF %pick%==1 call :getLetter
IF %pick%==2 call :getNumber
GOTO :EOF
:getLetter
Set /a Letter=%random% * 26 / 32768 + 1
IF %letter%==1 Set disp!dig!=a
REM repeat for each letter value between a and z
IF %letter%==26 Set disp!dig!=z
GOTO :EOF
:getNumber
Set /a number=%random% * 10 / 32768 + 1
IF %number%==1 Set disp!dig!=0
REM repeat for every number value between zero and 9
IF %number%==9 Set disp!dig!=9
GOTO :EOF
:result
ECHO %disp1%%disp2%%disp3%%disp4%%disp5%-%disp6%%disp7%%disp8%%disp9%%disp10%-
%disp11%%disp12%%disp13%%disp14%%disp15%-%disp16%%disp17%%disp18%%disp19%%disp20%
pause >nul
GOTO open

Accuracy of Decimals in a Batch Program

Trying to create a batch program (I have no other option but only use batch) that can accept a decimal input, the input is only specific up to two decimal places. My problem is how I can round-off the output to improve accuracy. For example the user input is 100.77*0.80, the answer is 80.616, I can only output 80.61 and not 80.616, I want an output of 80.62. And my bigger problem is that the decimal answer will be used to subtract from the original amount which will cause a Mathematical mistake in the decimal level. The answer will be 80.61 and 20.16.
Here's my program:
#echo off
setlocal EnableDelayedExpansion
set decimals=2
set /A one=1, decimalsP1=decimals+1
for /L %%i in (1,1,%decimals%) do set "one=!one!0"
:getFee
set /P "Amt=Enter the Amount (100.00): "
set /P "Disc=Enter the Discount Percentage: "
if "!Amt:~-%decimalsP1%,1!" equ "." goto AmtDeci
:getNumber
goto NoDeci
:AmtDeci
set "fpA=%Amt:.=%"
set "fpB=%Disc:.=%"
set /A mul=fpA*fpB/one
set discout=!mul:~0,-2!.!mul:~-2!
echo The Discount is: %discout%
set /A "fpD=%discout:.=%"
set /A sub=fpA-fpD
set Amtout=!sub:~0,-%decimals%!.!sub:~-%decimals%!
echo The Amount less discount is: %Amtout%
pause
Exit /B
:NoDeci
set /a discout=%Amt%*%Disc%/100
set /a Amtout=%Amt%-discout
echo The Amount less Discount is: %Amtout%
echo The Discount is: %discout%
pause
I assume you are using the method described at this answer. You always should include a link to the original source of your code.
What you want to do is very simple: just add the equivalent of 0.5 to the result of the multiplication before divide it by one:
set /A mul=(fpA*fpB+50)/one
Output example:
Enter the Amount (100.00): 100.77
Enter the Discount Percentage: 80
The Discount is: 80.62
The Amount less discount is: 20.15

Simple math program wont work?

I'm trying to create a batch program that will add the input to 232, then divide the result by 470. It would also be nice if someone told me how to make it so that if the user inputs a letter instead of a number, or an invalid character, anything besides a number, the program would execute a "goto command." Thanks!
PS the current code outputs 0, regardless of input.
Heres my code:
#echo off
title Grade
:1
cls
set /p input= "Grade: "
set /a input1= input + 232
set /a input2= input1 / 470
echo %input2%
pause
goto 1
For your division equation, batch files do not support floating point arithmetic, so you won't get a true answer. Anything less than 238 for input returns a 0 for your quotient.
Here's some code to let you see how to guarantee numeric input.
:Blurb
#Echo off
Cls
Echo Grade Math
:GetNum
Echo.
Set /p _Input="Grade: "
Set "_Num="
For /f "delims=0123456789" %%i in ("%_Input%") Do Set "_Num=%%i"
If Defined _Num Echo.&Echo Invalid: please enter a number.&Goto :GetNum
:DoMath
Set /a _Sum= _Input + 232
Echo Sum = %_Sum%
Set /a _Quotient= _Sum / 470
Echo Quotient = %_Quotient%
Pause
Goto :GetNum
:End

Batch Calcs.. Not the same as usual

I'm trying to make a desktop binary calculator and can't seem to get values to calculate properly.
http://pastebin.com/embed_js.php?i=mtsJRys8
:: functions for 128
if userValue GEQ 128 (
set bin128 = 1
goto 64
)
if not userValue GEQ 128 (
set bin128 = 0
)
Trying to get the Variable 'bin128' to end with a value 1 or 0
Decimal to binary converter?
I see in your paste you're computing the binary result by comparing the entered number with powers of two. There's a more efficient algorithm for converting dec to bin, and it'll handle numbers from 0 to 2147483647.
#echo off
setlocal
if "%~1"=="" (
echo usage: %~nx0 integer
goto :EOF
)
set /a dec = %~1
:/2
set /a mod = dec %% 2, dec /= 2
set "bin=%mod%%bin%"
if %dec% gtr 0 goto :/2
echo %bin%
I also see paulsm4's comment recommending another (suspicious quote) "real" language. Truthfully, though, not counting languages that already have a direct int-to-bin conversion method, the batch scripting language can actually save you a few steps because all math is integer math, with decimals inherently truncated. This saves you from having to Math.floor or similar on every iteration. This is one situation where batch is better-suited for the task than many other languages.
If you prefer to do the power-of-two comparison method, here's another solution. It loops 31 times regardless of the length of the numeral you supply, but for /L is very efficient. This may actually be faster than the method above for larger numbers for many iterations. Not sure.
#echo off
setlocal enabledelayedexpansion
if "%~1"=="" (
echo usage: %~nx0 integer
goto :EOF
)
set /a dec = %~1, pow = 1073741824
for /L %%I in (1,1,31) do (
if !dec! geq !pow! (
set "bin=!bin!1"
set /a dec -= pow
) else (
if defined bin set "bin=!bin!0"
)
set /a pow /= 2
)
if not defined bin set bin=0
echo %bin%
And just because I felt like it, here's the same thing but using bitwise operations. This is the most efficient method. (Edit: or at least it was, until Aacini posted his solution.)
#echo off
setlocal enabledelayedexpansion
if "%~1"=="" (
echo usage: %~nx0 integer
goto :EOF
)
for /L %%I in (0,1,30) do (
set /a "mask = 1 << %%I, bit = ^!^!(%~1 & mask)"
if !mask! gtr %~1 goto break
set "bin=!bit!!bin!"
)
:break
if not defined bin set bin=0
echo %bin%
Efficiency:
I ran a series of tests to determine which method is most efficient. For each method, I sent the output to NUL, looped the script for 1000 iterations, then took an average of the run times over 3 runnings. I did this first with a small value of 5, then a large value of 2147483646. Results:
goto method, input=small: 7.37 seconds
goto method, input=large: 33.77 seconds
powers-of-two method, input=small: 8.38 seconds
powers-of-two method, input=large: 12.44 seconds
bitwise method, input=small: 6.35 seconds
bitwise method, input=large: 11.42 seconds
These results are not surprising, as for /L is generally faster than a goto loop, and bitwise operations occur faster than integer math.
Just to complete rojo's answer, I think that this is the most efficient method to convert a decimal number to binary:
#echo off
setlocal EnableDelayedExpansion
if "%~1"=="" (
echo usage: %~nx0 integer
goto :EOF
)
set "decimal=%~1"
set "binary="
for /L %%i in (1,1,32) do (
set /A "bit=decimal&1, decimal>>=1"
set "binary=!bit!!binary!"
if !decimal! equ 0 goto break
)
:break
echo %binary%
Note that previous method correctly convert negative numbers!
At this post there is a Batch file that can convert very large decimal numbers to binary. The result is stored in a Batch variable, so the binary number may have a maximum of 8 K digits. This means that the maximum decimal number that can be converted is 2^8192 - 1.

Floating point division in a batch file

I need to do a floating-point division in a dos batch.
I didn't find a way to do it. Something like this :
SET /A Res=10/3
returns a integer number.
Is it possible to do it ?
I know this is a very old topic, but I can't found a simple Batch method in all previous answers, so I post here a pure Batch solution that is very simple to use.
Perform operations using fixed point arithmetic in Batch is simple. "Fixed point" means that you must set a number of decimals in advance and keep it throughout the operations. Add and subtract operations between two Fixed Point numbers are performed directly. Multiply and division operations requires an auxiliary variable, that we can call "one", with the value of 1 with the right number of decimals (as "0" digits). After multiply, divide the product by "one"; before division, multiply the dividend by "one". Here it is:
#echo off
setlocal EnableDelayedExpansion
set decimals=2
set /A one=1, decimalsP1=decimals+1
for /L %%i in (1,1,%decimals%) do set "one=!one!0"
:getNumber
set /P "numA=Enter a number with %decimals% decimals: "
if "!numA:~-%decimalsP1%,1!" equ "." goto numOK
echo The number must have a point and %decimals% decimals
goto getNumber
:numOK
set numB=2.54
set "fpA=%numA:.=%"
set "fpB=%numB:.=%"
set /A add=fpA+fpB, sub=fpA-fpB, mul=fpA*fpB/one, div=fpA*one/fpB
echo %numA% + %numB% = !add:~0,-%decimals%!.!add:~-%decimals%!
echo %numA% - %numB% = !sub:~0,-%decimals%!.!sub:~-%decimals%!
echo %numA% * %numB% = !mul:~0,-%decimals%!.!mul:~-%decimals%!
echo %numA% / %numB% = !div:~0,-%decimals%!.!div:~-%decimals%!
For example:
Enter a number with 2 decimals: 3.76
3.76 + 2.54 = 6.30
3.76 - 2.54 = 1.22
3.76 * 2.54 = 9.55
3.76 / 2.54 = 1.48
Batch files as such do not support the floating point arithmetic. However, this article suggests a workaround that uses an external script file to do calculations. The script file should use some sort of eval function to evaluate the expression passed as an argument and return the result. Here's a sample VBScript file (eval.vbs) that does this:
WScript.Echo Eval(WScript.Arguments(0))
You can call this external script from your batch file, specify the expression to be evaluated and get the result back. For example:
#echo off
for /f %%n in ('cscript //nologo eval.vbs "10/3"') do (
set res=%%n
)
echo %res%
Of course, you'll get the result as a string, but it's better than nothing anyway, and you can pass the obtained result to the eval script as part of another expression.
According to this reference, there is no floating point type in DOS batch language:
Although variables do exist in the DOS batch programming language, they are extremely limited. There are no integer, pointer or floating point variable types, only strings.
I think what you are trying to do will be impossible without implementing your own division scheme to calculate the remainder explicitly.
I recently came across this batch file to compute an approximation of Pi.
There is a DivideByInteger label that might be useful to you: Stupid-Coding-Tricks-A-Batch-of-Pi
It uses a set of MaxQuadIndex variables, each containing a four-digit number (quadruple), in order to store the entire result. The code allows division by an integer between 1 and 10000, inclusive.
:DivideByInteger
if defined PiDebug echo.DivideByInteger %1 %2
set /a DBI_Carry = 0
for /L %%i in (!MaxQuadIndex!, -1, 0) do (
set /a DBI_Digit = DBI_Carry*10000 + %1_%%i
set /a DBI_Carry = DBI_Digit %% %2
set /a %1_%%i = DBI_Digit / %2
)
goto :EOF
A Print label is also available…
try this
SETLOCAL EnableExtensions EnableDelayedExpansion
call :calc_ 1 (99-(100*5/100^)^)
echo !calc_v!
goto :EOF
:calc_
set scale_=1
set calc_v=
for /l %%i in (1,1,%1) do set /a scale_*=10
set /a "calc_v=!scale_!*%2"
set /a calc_v1=!calc_v!/!scale_!
set /a calc_v2=!calc_v!-!calc_v1!*!scale_!
set calc_v=!calc_v1!.!calc_v2!
goto :EOF
just change
call :calc_ decimalpoint equataion
in the example
decimalpoint is 1
equataion is (99-(100*5/100^)^) ;make sure if you use () that you insert ^ before ) as in ^)
the answer is 94.0
if decimalpoint is 2
and equataion is 22/7 ;π pi
the answer is 3.14
I wrote a pure batch file specifically to do division. It takes the first number you input, and then divides it by the second one, and displays the result with as many decimal points as you specify.
Echo off
cls
if NOT "%3" == "" (
set n1=%1
set n2=%2
set max=%3
goto :begin
)
set counter=2
set n1=1
set n2=1
set ans=
:start
Echo.
Echo. 1 / 2
Echo.
Set /p N1= 1?
set /p N2= 2?
Set /p Max= Out how many Decimal Points?
:begin
set /a TmpAns=%N1%/%N2%
set ans=%TmpAns%.
:: Echo.%ans%.>Answer.txt
<nul set /p "=%Tmpans%."
set /a TmpSub=%N2%*%TmpAns%
set /a N1=%N1%-%TmpSub%
set N1=%N1%0
If NOT "%n1%" == "00" (
if %n1% LSS %N2% (
set N1=%N1%0
set ans=%ans%0
)
) else (
Goto :Finished
)
set count=0
:loop
If "%count%" == "%max%" (
Goto :Finished
)
set /a TmpAns=%N1%/%N2%
set ans=%ans%%TmpAns%
<nul set /p "=%Tmpans%"
set /a TmpSub=%N2%*%TmpAns%
set /a N1=%N1%-%TmpSub%
set N1=%N1%0
If NOT "%n1%" == "00" (
if %n1% LSS %N2% (
set N1=%N1%0
set ans=%ans%0
)
) else (
Goto :Finished
)
set /a count=%count%+1
goto :loop
:finished
cls
Echo.
Echo.
Echo.The Number
Echo.%ans%
Echo.
Echo.
set n1=1
set n2=1
pause
goto :eof
:eof
The answer put into the variable %Ans%. It can also be called with parameters. ("Divide.bat 50 27 5" would give you 50/27 out 5 decimal points.)
Since nowadays PowerShell is present on almost all machines, I would let PowerShell do the math and return the result to the batch.
Example:
set divident=10
set divisor=3
for /f "delims=" %%a in ('powershell -Command %divident%/%divisor%') do set result=%%a
#echo %result%
Explanation:
Input variables: Use set variables to define divident and divisor.
Calling powershell and assign result to a batch variable: for /f "delims=" %%a in ('powershell -Command ...) do set result=%%a (you may also check here: How to put a single PowerShell output string into a cmd variable?)
Note the above code will only work with integer input variables.
To support floating point input variables, we need to send the variables as strings inside quotations ("%variable%") and convert the strings within PowerShell back to Double, otherwise batch would interpret the commas as delimiters and PowerShell could not interpret the numbers.
Example:
set divident=10,5
set divisor=3,4
for /f "delims=" %%a in ('powershell -Command [convert]::ToDouble^(\"%divident%\"^)
/[convert]::ToDouble^(\"%divisor%\"^)') do set result=%%a
#echo %result%
Explanation:
Note in PowerShell you would do this like [convert]::ToDouble("10,5")/[convert]::ToDouble("3,5"). However in batch we need to escape the quotes using backslash, and we also need to add a "^" sign before and after the quoted parts: [convert]::ToDouble^("%divident%"^)/[convert]::ToDouble^("%divisor%"^)
If you're running in a command shell on Windows (rather than DOS), you can use VBScript to evaluate complex expressions including floating point math for you.
I have written a small helper library you can call to do this.
EvalBat Library on GitHub

Resources