使无符号的 int 值成为有符号的 int 值并返回
Make signed int value from unsigned int value and back
我需要将无符号整数序列转换为有符号整数序列,并保持元素的顺序。
理想情况下,我需要这样的函数
template <typename T>
std::make_signed_t<T> MakeSigned(T val);
template <typename T>
std::make_unsigned_t<T> MakeUnsigned(T val);
实施它们的正确方法是什么?
编辑1:
函数 MakeSigned 和 MakeUnsigned 应满足以下条件:
对于给定的参数对 a、b 和返回值 a1、b1,如果 a <= b,则 a1 <= b1。
并且对于给定的签名
MakeSigned(MakeUnsigned(a)) == a
编辑2:
MakeSigned 这样做(对于给定的类型uint8_t、uint16_t、uint32_t uint64_t(:
0 => INT_MIN
UINT_MAX => INT_MAX
制作未签名:
INT_MIN => 0
INT_MAX => UINT_MAX
一种解决方案是在映射到/从unsigned
类型映射时减去/添加偏差项std::numeric_limits<Signed>::min()
。计算必须使用无符号算术完成,该算术包装不会产生未定义的行为:
#include <iostream>
#include <type_traits>
#include <limits>
#include <cstdint>
template<typename T>
typename std::enable_if_t<std::is_unsigned_v<T>, std::make_signed<T>>::type map_to_signed(T val) {
using U = std::make_signed_t<T>;
return val + std::numeric_limits<U>::min(); // Wrapping unsigned addition.
}
template<typename T>
typename std::enable_if_t<std::is_signed_v<T>, std::make_unsigned<T>>::type map_to_unsigned(T val) {
using U = std::make_unsigned_t<T>;
return static_cast<U>(val) - std::numeric_limits<T>::min(); // Wrapping unsigned subtraction.
}
int main() {
std::cout << map_to_signed(0u) << 'n';
std::cout << map_to_unsigned(map_to_signed(0u)) << "nn";
std::cout << std::numeric_limits<int>::max() << 'n';
std::cout << map_to_unsigned(std::numeric_limits<int>::max()) << 'n';
std::cout << map_to_signed(map_to_unsigned(std::numeric_limits<int>::max())) << "nn";
std::cout << std::numeric_limits<unsigned>::max() << 'n';
std::cout << map_to_signed(std::numeric_limits<unsigned>::max()) << 'n';
std::cout << map_to_unsigned(map_to_signed(std::numeric_limits<unsigned>::max())) << "nn";
std::cout << std::numeric_limits<uint64_t>::max() << 'n';
std::cout << map_to_signed(std::numeric_limits<uint64_t>::max()) << 'n';
std::cout << map_to_unsigned(map_to_signed(std::numeric_limits<uint64_t>::max())) << "nn";
}
输出:
-2147483648
0
2147483647
4294967295
2147483647
4294967295
2147483647
4294967295
18446744073709551615
9223372036854775807
18446744073709551615
我会简单地翻转符号位:
template <typename T>
std::make_signed_t<T> MakeSigned(T val)
{
return val ^ (1u << (sizeof(T) * 8 - 1));
}
template <typename T>
std::make_unsigned_t<T> MakeUnsigned(T val)
{
return val ^ (1u << (sizeof(T) * 8 - 1));
}
有趣的是,您没有要求这些函数保留a
和b
的值。这很好,因为如果是这样,那么它们将无法实施。
因此,您希望在转换时"偏移"值。
所以int(0)
变得unsigned(std::numeric_limits<int>::max()+1)
,unsigned(0)
变得std::numeric_limits<int>::min()
有了这个,以及Maxim的结构,你应该能够编写你需要的函数。
哦,如果你使用INT_MIN
和INT_MAX
而不是numeric_limits
,你会失败的。
相关文章:
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 从 std::vector<无符号字符>切片中提取 int?
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- LibPrivoxy: 未解析的外部符号 __declspec(dllimport) int __stdcall Sta
- C++无符号短裤的划分导致 int
- 错误:隐式转换更改符号:'int'到'unsigned long'
- 将无符号转换为复杂<int>原因符号转换警告
- 如何解决隐式转换丢失整数精度:'size_t'(又名"无符号长")到'int'警告?
- 无符号的 int 到有效数字
- C++:使用没有位移位的指针将无符号字符转换为无符号 int
- 整数类型应该显式转换(例如"int"到"无符号")还是只会增加混乱?
- 有没有办法在C++中将mpz_t转换为 int 或无符号长 int?
- 是否可以将无符号 int 的最大值转换为 int 并将结果转换为 -1?
- C++ std::vector<int> 体系结构的未定义符号 x86_64:
- 为什么QByteArray的大小是"int"而不是"无符号int"
- 与 string.size() 比较时 int 的符号性显示警告
- 为什么 (-i) 的类型(其中 i 是无符号的 int)仍然是无符号的 int?
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?