Bu betik hakkında öyle uzun uzun açıklama yapmayı gerek görmüyorum.Sıradan basit ama çok güçlü karmaşık işlemler yapabilen bir konsol hesap makinesidir.
KOD İÇERİĞİ : ( Simple Calculator v1.0.ps1)
Kod: Tümünü seç
# ============================================================
# Simple Windows PowerShell Calculator
# System : Windows 11
#
# Supports: + - * / % ^ (power) and parentheses, plus these functions:
# sin, cos, tan, asin, acos, atan (trigonometric - ANGLES IN RADIANS)
# sqrt, abs, exp, log (base 10), ln (natural log), pow(x, y)
#
# SAFETY: Uses a custom recursive-descent parser, not Invoke-Expression
# or any generic evaluator. Only numbers, the operators above, and the
# whitelisted function names below are ever recognized - anything else
# (letters that aren't a known function, variables, PowerShell syntax,
# semicolons, etc.) is rejected before evaluation ever begins. This is
# the same safety guarantee as bash's 'bc': math only, no code execution.
# ============================================================
$AllowedFunctions = @('sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'sqrt', 'abs', 'exp', 'log', 'ln', 'pow')
function Invoke-MathFunction {
param([string]$Name, [double[]]$Arguments)
switch ($Name.ToLower()) {
'sin' { return [math]::Sin($Arguments[0]) }
'cos' { return [math]::Cos($Arguments[0]) }
'tan' { return [math]::Tan($Arguments[0]) }
'asin' { return [math]::Asin($Arguments[0]) }
'acos' { return [math]::Acos($Arguments[0]) }
'atan' { return [math]::Atan($Arguments[0]) }
'sqrt' { return [math]::Sqrt($Arguments[0]) }
'abs' { return [math]::Abs($Arguments[0]) }
'exp' { return [math]::Exp($Arguments[0]) }
'log' { return [math]::Log10($Arguments[0]) }
'ln' { return [math]::Log($Arguments[0]) }
'pow' {
if ($Arguments.Count -lt 2) { throw "pow() requires two arguments: pow(base, exponent)" }
return [math]::Pow($Arguments[0], $Arguments[1])
}
default { throw "Unknown function: $Name" }
}
}
# --- TOKENIZER ---
function Get-Tokens {
param([string]$Expr)
$pattern = '\d+\.?\d*|[A-Za-z]+|[\+\-\*/\^%\(\),]'
$matches = [regex]::Matches($Expr, $pattern)
$cleanInput = $Expr -replace '\s', ''
$matchedLength = ($matches | ForEach-Object { $_.Value } | Measure-Object -Property Length -Sum).Sum
if ($matchedLength -ne $cleanInput.Length) {
throw "Input contains characters that are not numbers, allowed operators, or known function names."
}
return @($matches | ForEach-Object { $_.Value })
}
# --- RECURSIVE DESCENT PARSER / EVALUATOR ---
$script:tokens = @()
$script:pos = 0
function Peek-Token { if ($script:pos -lt $script:tokens.Count) { return $script:tokens[$script:pos] } else { return $null } }
function Read-Token { $t = Peek-Token; $script:pos++; return $t }
function Parse-Expression {
$value = Parse-Term
while ((Peek-Token) -in @('+', '-')) {
$op = Read-Token
$rhs = Parse-Term
if ($op -eq '+') { $value += $rhs } else { $value -= $rhs }
}
return $value
}
function Parse-Term {
$value = Parse-Power
while ((Peek-Token) -in @('*', '/', '%')) {
$op = Read-Token
$rhs = Parse-Power
switch ($op) {
'*' { $value = $value * $rhs }
'/' {
if ($rhs -eq 0) { throw "Division by zero." }
$value = $value / $rhs
}
'%' { $value = $value % $rhs }
}
}
return $value
}
function Parse-Power {
$value = Parse-Unary
if ((Peek-Token) -eq '^') {
Read-Token | Out-Null
$rhs = Parse-Power
$value = [math]::Pow($value, $rhs)
}
return $value
}
function Parse-Unary {
if ((Peek-Token) -eq '-') {
Read-Token | Out-Null
return -1 * (Parse-Unary)
}
return Parse-Primary
}
function Parse-Primary {
$t = Peek-Token
if ($null -eq $t) { throw "Unexpected end of expression." }
if ($t -match '^\d') {
Read-Token | Out-Null
return [double]::Parse($t, [System.Globalization.CultureInfo]::InvariantCulture)
}
if ($t -eq '(') {
Read-Token | Out-Null
$value = Parse-Expression
if ((Peek-Token) -ne ')') { throw "Missing closing parenthesis." }
Read-Token | Out-Null
return $value
}
if ($t -match '^[A-Za-z]+$') {
if ($t.ToLower() -notin $AllowedFunctions) {
throw "Unknown or unsupported function: '$t'"
}
$funcName = Read-Token
if ((Peek-Token) -ne '(') { throw "Expected '(' after function name '$funcName'." }
Read-Token | Out-Null
$argsList = @(Parse-Expression)
while ((Peek-Token) -eq ',') {
Read-Token | Out-Null
$argsList += Parse-Expression
}
if ((Peek-Token) -ne ')') { throw "Missing closing parenthesis for function '$funcName'." }
Read-Token | Out-Null
return Invoke-MathFunction -Name $funcName -Arguments $argsList
}
throw "Unexpected token: '$t'"
}
function Show-Header {
Clear-Host
Write-Host "============================================" -ForegroundColor Blue
Write-Host " Simple Windows PowerShell Calculator " -ForegroundColor Blue
Write-Host "============================================" -ForegroundColor Blue
Write-Host ""
}
# --- MAIN LOOP ---
while ($true) {
Show-Header
Write-Host "Enter an arithmetic expression:"
Write-Host "(Supported: + - * / % ^ ( ) and sin cos tan asin acos atan sqrt abs exp log ln pow - angles in RADIANS)" -ForegroundColor DarkGray
$userInput = Read-Host
try {
$script:tokens = Get-Tokens -Expr $userInput
$script:pos = 0
if ($script:tokens.Count -eq 0) { throw "Empty expression." }
$numericResult = Parse-Expression
if ($script:pos -lt $script:tokens.Count) {
throw "Unexpected token after end of expression: '$(Peek-Token)'"
}
$invariant = [System.Globalization.CultureInfo]::InvariantCulture
Write-Host ""
Write-Host "Two decimal places of precision:"
Write-Host $numericResult.ToString("F2", $invariant)
Write-Host "Ten decimal places of precision:"
Write-Host $numericResult.ToString("F10", $invariant)
Write-Host "Rounded integer value:"
Write-Host ([math]::Round($numericResult, 0, [MidpointRounding]::AwayFromZero))
} catch {
Write-Host ""
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host ""
Write-Host "Press ENTER to exit, or press 'R' to run another calculation..." -ForegroundColor Yellow
$key = [Console]::ReadKey($true)
if ($key.KeyChar -eq 'r' -or $key.KeyChar -eq 'R') {
continue
} else {
break
}
}


