¿Por qué los enteros en PowerShell se comparan por dígitos?
comparison operators (4)
Mi código le dice si su número adivinado es mayor o menor que un número generado aleatoriamente, pero parece que solo compara los primeros dígitos del número cuando uno de ellos está por debajo de 10.
[int]$GeneratedNum = Get-Random -min 1 -max 101
Write-Debug $GeneratedNum
$isQuitting = $false
Do{
[int]$Input = Read-Host "Take a guess!"
If($Input -lt $GeneratedNum){Write-Output "Too Low"}
If($Input -gt $GeneratedNum){Write-Output "Too High"}
If($Input -eq $GeneratedNum){Write-Output "Good Job!"; $isQuitting = $true}
} Until($isQuitting -eq $true)
Por ejemplo, cuando
$GeneratedNum = 56
y
$Input = 7
, devuelve
"Too High"
El problema proviene del hecho de que
Read-Host
devuelve una cadena, por lo que con su conversión
$Input
es un intento
ArrayListEnumeratorSimple
:
[int]$GeneratedNum = Get-Random -min 1 -max 101
Write-host $GeneratedNum
$isQuitting = $false
Do{
$Input = (Read-Host "Take a guess!") -as [int]
If($Input -lt $GeneratedNum){Write-Output "Too Low"}
If($Input -gt $GeneratedNum){Write-Output "Too High"}
If($Input -eq $GeneratedNum){Write-Output "Good Job!"; $isQuitting = $true}
} Until($isQuitting -eq $true)
También debe usar
try{}catch{}
para detectar el caso de que la entrada no sea un int.
Lo que debe entender es que cuando usa operadores de comparación de PowerShell, el tipo de la parte izquierda se usa seleccionado, por lo que la parte derecha se convierte en el tipo izquierdo.
Sabiendo que podría haber escrito lo siguiente, donde acabo de poner el
$GeneratedNum
que es un número entero a la izquierda de las comparaciones:
[int]$GeneratedNum = Get-Random -min 1 -max 101
Write-host $GeneratedNum
$isQuitting = $false
Do{
$Input = (Read-Host "Take a guess!")
If($GeneratedNum -gt $Input){Write-Output "Too Low"}
If($GeneratedNum -lt $Input){Write-Output "Too High"}
If($GeneratedNum -eq $Input){Write-Output "Good Job!"; $isQuitting = $true}
} Until($isQuitting -eq $true)
Esto se debe a que estás comparando una cadena con un número entero. El orden importa.
"56" -lt 7
En realidad es lo mismo que:
"56" -lt "7"
Alternativamente:
56 -lt "7"
te daría el resultado correcto. PowerShell intenta forzar el argumento del lado derecho al tipo del lado izquierdo.
Puede intentar un reparto explícito:
[int]$Input -lt $GeneratedNum
Nunca use una variable con el mismo nombre que una variable automática:
$input
es una variable automática.
Vea este código, donde canalizo el valor leído desde el host (y no uso la variable
$input
):
[int]$GeneratedNum = Get-Random -min 1 -max 101
Write-Debug $GeneratedNum
$isQuitting = $false
Do{
Read-Host "Take a new guess!" | %{
if($_ -as [int] -gt 0){
If($_ -lt $GeneratedNum){Write-Output "Too Low"}
If($_ -gt $GeneratedNum){Write-Output "Too High"}
If($_ -eq $GeneratedNum){Write-Output "Good Job!"; $isQuitting = $true}
}
}
} Until($isQuitting -eq $true)
Es importante tener en cuenta que mi código trata correctamente las entradas
incorrectas
(caracteres no numéricos) como
w
o como cadenas (
qwerty
), lo que hace que las otras propuestas fallen.
Aprovecho el hecho de que usted genera enteros siempre mayores que 0.
Usando un
switch
:
[int]$GeneratedNum = Get-Random -min 1 -max 101
Write-Debug $GeneratedNum
:lop Do{
switch ((Read-Host ''Take a new guess!'') -as [int])
{
{$_ -eq $null}{continue}
{$_ -lt $GeneratedNum}{''Too Low'';continue}
{$_ -gt $GeneratedNum}{''Too High'';continue}
{$true}{''Good Job!'';break lop}
}
} while($true)