如何将有符号整数格式化为可识别符号的十六进制表示? [英] How do I format a signed integer to a sign-aware hexadecimal representation?

查看:16
本文介绍了如何将有符号整数格式化为可识别符号的十六进制表示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最初的意图是以保留数字符号的方式将带符号的原始数字转换为其十六进制表示.事实证明,LowerHexUpperHex 的当前实现以及带符号原始整数的亲属将简单地将它们视为无符号.不管我添加了哪些额外的格式化标志,这些实现似乎只是将数字重新解释为用于格式化目的的未签名对应项.(游乐场)

My initial intent was to convert a signed primitive number to its hexadecimal representation in a way that preserves the number's sign. It turns out that the current implementations of LowerHex, UpperHex and relatives for signed primitive integers will simply treat them as unsigned. Regardless of what extra formatting flags that I add, these implementations appear to simply reinterpret the number as its unsigned counterpart for formatting purposes. (Playground)

println!("{:X}", 15i32);           // F
println!("{:X}", -15i32);          // FFFFFFF1   (expected "-F")
println!("{:X}", -0x80000000i32);  // 80000000   (expected "-80000000")
println!("{:+X}", -0x80000000i32); // +80000000
println!("{:+o}", -0x8000i16);     // +100000
println!("{:+b}", -0x8000i16);     // +1000000000000000

std::fmt 不清楚这是否应该发生,甚至是否有效,UpperHex (或任何其他格式特征)没有提到有符号整数的实现将数字解释为无符号.Rust 的 GitHub 存储库上似乎也没有相关问题.(后增补通知:1.24.0 开始,文档已得到改进以正确解决这些问题,请参阅问题 #42860)

The documentation in std::fmt is not clear on whether this is supposed to happen, or is even valid, and UpperHex (or any other formatting trait) does not mention that the implementations for signed integers interpret the numbers as unsigned. There seem to be no related issues on Rust's GitHub repository either. (Post-addendum notice: Starting from 1.24.0, the documentation has been improved to properly address these concerns, see issue #42860)

最终,可以为任务实现特定功能(如下所示),但不幸的是与格式化程序 API 不太兼容.

Ultimately, one could implement specific functions for the task (as below), with the unfortunate downside of not being very compatible with the formatter API.

fn to_signed_hex(n: i32) -> String {
    if n < 0 {
        format!("-{:X}", -n)
    } else {
        format!("{:X}", n)
    }
}

assert_eq!(to_signed_hex(-15i32), "-F".to_string());

有符号整数类型的这种行为是故意的吗?有没有办法在遵守标准 格式化程序?

Is this behaviour for signed integer types intentional? Is there a way to do this formatting procedure while still adhering to a standard Formatter?

推荐答案

有没有办法在遵守标准的同时执行此格式化程序 格式化程序?

是的,但是您需要创建一个新类型才能提供 UpperHex 的独特实现.这是一个尊重 +#0 标志的实现(可能还有更多,我还没有测试过):

Yes, but you need to make a newtype in order to provide a distinct implementation of UpperHex. Here's an implementation that respects the +, # and 0 flags (and possibly more, I haven't tested):

use std::fmt::{self, Formatter, UpperHex};

struct ReallySigned(i32);

impl UpperHex for ReallySigned {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let prefix = if f.alternate() { "0x" } else { "" };
        let bare_hex = format!("{:X}", self.0.abs());
        f.pad_integral(self.0 >= 0, prefix, &bare_hex)
    }
}

fn main() {
    for &v in &[15, -15] {
        for &v in &[&v as &UpperHex, &ReallySigned(v) as &UpperHex] {
            println!("Value: {:X}", v);
            println!("Value: {:08X}", v);
            println!("Value: {:+08X}", v);
            println!("Value: {:#08X}", v);
            println!("Value: {:+#08X}", v);
            println!();
        }
    }
}

这篇关于如何将有符号整数格式化为可识别符号的十六进制表示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆