如何创建一个f16重复n次的数字?

问题描述

我需要创建一个数字,其中(f) 16 重复n次。 0

我尝试了以下示例,例如n = 16

std::cout << "hi:" << std::hex << std::showbase << (1ULL << 64) - 1 << std::endl;

警告:移位计数> =类型[-Wshift-count-overflow]的宽度 std :: cout

hi:0x200

如何获取所有数字f而不会溢出ULL

解决方法

其中(f)16重复n次。

如果我正确地理解了这一点,我相信这是微不足道的。添加一个f。将数字左移4位。添加另一个f。向左移4位。添加另一个f。重复n次。

#include <stdio.h>
unsigned long long gen(unsigned n) {
     unsigned long long r = 0;
     while (n--) {
         r <<= 4;
         r |= 0xf;
     }
     return r;
}
int main() {
    for (int i = 0; i < 16; ++i) {
        printf("%d -> %llx\n",i,gen(i));
    }
}

输出:

0 -> 0
1 -> f
2 -> ff
3 -> fff
4 -> ffff
5 -> fffff
6 -> ffffff
7 -> fffffff
8 -> ffffffff
9 -> fffffffff
10 -> ffffffffff
11 -> fffffffffff
12 -> ffffffffffff
13 -> fffffffffffff
14 -> ffffffffffffff
15 -> fffffffffffffff
,

对于n = 1到16,您可以从所有F开始,然后相应地移动:

0xFFFFFFFFFFFFFFFFULL >> (4*(16-n));

(分别处理n = 0)

,

由于如果4*n是16位而n是64位,则移位unsigned long long位是有问题的,因此可以通过较小的移位来解决问题。如果已知n是正数,我们可以将其分为两个移位:

(1ull << 4 << 4*(n-1)) - 1u

而且,由于1ull << 4是一个常量,我们可以替换它:

(0x10ull << 4*(n-1)) - 1u

如果n可以为零,则为了支持0到16之间的任何值,我们不能使用单个表达式。一个解决方案是:

n ? 0 : (0x10ull << 4*(n-1)) - 1u
,

如果您只是以十六进制格式和数字f来打扰,请使用其他答案。

下面的函数可以生成十六进制和十进制格式以及任何数字的数字。

#include <iostream>

uint64_t getNum(uint64_t digit,uint64_t times,uint64_t base)
{
    if (base != 10 && base != 16) return 0;
    if (digit >= base) return 0;
    
    uint64_t res = 0;
    uint64_t multiply = 1;
    for(uint64_t i = 0; i < times; ++i)
    {
        res += digit * multiply;
        multiply *= base;
    }
    return res;
}

int main() {
    std::cout << getNum(3,7,10) << std::endl;
    std::cout << std::hex << getNum(0xa,14,16) << std::dec << std::endl;
    return 0;
}

输出:

3333333
aaaaaaaaaaaaaa

注意:当前代码没有溢出检测。

,

您可以编写一个单独的函数,例如通过以下方式查找。

#include <stdio.h>

unsigned long long create_hex( size_t n )
{
    unsigned long long x = 0;
    
    n %= 2 * sizeof( unsigned long long );

    while ( n-- )
    {
        x = x << 4 | 0xf;
    }
    
    return x;
}

int main( void ) 
{
    for ( size_t i = 0; i <= 16; i++ )
    {
        printf( "%zu -> %llx\n",create_hex( i ) );
    }
}   

程序输出为

0 -> 0
1 -> f
2 -> ff
3 -> fff
4 -> ffff
5 -> fffff
6 -> ffffff
7 -> fffffff
8 -> ffffffff
9 -> fffffffff
10 -> ffffffffff
11 -> fffffffffff
12 -> ffffffffffff
13 -> fffffffffffff
14 -> ffffffffffffff
15 -> fffffffffffffff
16 -> 0

最初,您使用的是两种语言标记,即C和C ++,然后将该程序作为C ++程序运行,将标头<stdio.h>替换为<iostream>,并使用运算符printf。