如何在PowerShell中将十六进制小数转换为十进制?

3
有没有办法在PowerShell中将十六进制小数(例如:用十六进制表示的值小于1.0的数字)转换为十进制数?以下是示例:
Hex                  Dec
0.0858b9da24fb4cac = 0.032603851087498366
0.8c3115559ab0c10b = 0.5476239522928976

我发现的一般十六进制/十进制转换指南建议使用[Convert],这对于整数来说很好,但是当我在字符串中加入小数点时,它似乎完全失效。

注意:这些示例是从另一个网站的数据中获取的,在那里进行了常规计算。我还没有完全验证它们的准确性 - 最后几位可能会有误差。幸运的是,我不需要那么高的精度。

2个回答

4
我不知道有没有内置的 .Net 方法可以实现这个功能。我写了一个暴力转换器,但是你的值似乎与 .Net 类型精度不完全匹配 - [double] (64 位) 精度太低,而 [decimal] (128 位) 更高。
你的示例输出如下:
0.0858b9da24fb4cac = 0.032603851087498366
                   = 0.0326038510874983682928164128

0.8c3115559ab0c10b = 0.5476239522928976
                   = 0.5476239522928976344718082711

代码:

<#
.Synopsis
   Converts strings containing hexadecimal numbers with fractional components
   into base-10 [decimal] numbers.

.EXAMPLE

   PS C:\> ConvertFrom-HexFraction '0.0858b9da24fb4cac'
   0.0326038510874983682928164128

.Example

   PS C:\> '0.0858b9da24fb4cac', '0.8c3115559ab0c10b' | ConvertFrom-HexFraction
   0.0326038510874983682928164128
   0.5476239522928976344718082711
#>
function ConvertFrom-HexFraction
{
    [CmdletBinding()]
    [OutputType([decimal])]
    Param
    (
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true)]
        [string]$hexValue
    )

    Process
    {
        # strip leading hex indicator, setup result placeholder of desired type.
        $hexValue = $hexValue -replace '^(0x|&h)'
        $result = [decimal]0

        # Loop over the digits (hexits?) in the string, skip the (hexa)decimal point '.'
        # and calculate (value * base ^ columnNum) for each.

        $i = $hexValue.IndexOf('.') - 1
        [char[]]$hexValue | Where { $_ -ne '.' } | ForEach {

            $result += [convert]::ToInt32($_, 16) * [Math]::Pow(16, $i--)

        }

        $result #output the result
    }

}


ConvertFrom-HexFraction '0.0'
ConvertFrom-HexFraction 'a.a'
ConvertFrom-HexFraction '0.0858b9da24fb4cac'
ConvertFrom-HexFraction '0.8c3115559ab0c10b'
'0.0858b9da24fb4cac', '0.8c3115559ab0c10b' | ConvertFrom-HexFraction 

FYI:在问题中添加了有关示例准确性的注释。 - Iszi

2

好的,这个引起了我的兴趣。我甚至不知道十六进制分数是一回事,所以我去查了一下。转换它们没有被包括在我能看到的[math][convert]库中,所以我们需要编写一个函数来处理它。我写了这个函数,它相对准确,但你必须考虑到一个像你那样小的分数会有一些舍入...我的意思是,就连你的第一个例子都进行了四舍五入。仅仅最后一位数字就是大约6.50521303491303E-19(这是12*(16^-16))。

因此,该函数如下:

Function HexToInt([string]$TextIn){
$Pre,$Post = $TextIn.split('.')

$PostConverted = For($i=1;$i -le $Post.Length;$i++){
    [convert]::ToInt32($Post[($i-1)],16) * [math]::pow(16,($i*-1))
}
$PostSum = $PostConverted | Measure-Object -Sum |% Sum
$Int = [convert]::ToInt64($Pre,16)
$Int+$PostSum
}

那应该为您转换您的分数。

“我甚至不知道十六进制小数是个啥东西”-- 这就是为什么到了2016年我们还没有好用的库例程来处理这类东西的原因!开玩笑啦,但是你懂我的意思。 ;) - alzee
FYI:在问题中添加了有关示例准确性的注释。 - Iszi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接