Why do integers in PowerShell compare by digits?

后端 未结 4 2026
执念已碎
执念已碎 2020-11-30 15:05

My code tells you whether your guessed number is higher or lower than a randomly generated number, but it seems to only compare the first digits of the number when one of th

相关标签:
4条回答
  • 2020-11-30 15:24

    The trouble come from the fact that Read-Host return a string so with your cast $Input is an ArrayListEnumeratorSimple try :

    [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)
    

    You also should use try{}catch{} to catch the case the input is not an int.

    The thing you must understand is that when you use PowerShell comparison operators, the type of the left part is used selected, so the rigth part is casted into the left type. Knowing that you could have write the following, where I just put the $GeneratedNum which is an integer on the left of the comparisons:

    [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)
    
    0 讨论(0)
  • 2020-11-30 15:26

    This is because you're comparing a string to an integer. The order matters.

    "56" -lt 7
    

    Is actually the same as:

    "56" -lt "7"
    

    Alternatively:

    56 -lt "7"
    

    would give you the correct result. PowerShell tries to coerce the right side argument to the type of the left side.

    You might try an explicit cast:

    [int]$Input -lt $GeneratedNum
    
    0 讨论(0)
  • 2020-11-30 15:42

    Using a 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)
    
    0 讨论(0)
  • 2020-11-30 15:43

    Never use a variable with the same name as an automatic variable: $input is an automatic variable.

    See this code, where I pipe the value read from host (and don't use the $input variable):

    [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)
    

    Important to notice that my code treats correctly wrong inputs (non numeric characters) like w or like strings (qwerty), which make the other proposals to fail.

    I make use of the fact that you generate integers always greater than 0.

    0 讨论(0)
提交回复
热议问题