我的意见是:
mask
的位掩码n
和某些偏移k
> = 0 pattern
,其中一些(但不一定是全部)位掩码具有1的位置为1。val
我想找到下一个最大的整数result
,以便:
result > val
result & mask == pattern
例如,假设mask = 0xFF00
和pattern = 0x0100
。然后我们期望得到以下结果:
NextLargest(mask, pattern, 0x00000) => 0x00100
NextLargest(mask, pattern, 0x000FF) => 0x00100
NextLargest(mask, pattern, 0x010FE) => 0x001FF
NextLargest(mask, pattern, 0x010FF) => 0x10100
另一个例子 - 说mask = 0xF
和pattern = 0xF
。然后我们期待:
NextLargest(mask, pattern, 0x20) => 0x2F.
我尝试过类似"删除mask
关心的位,增加它,或者返回pattern
并返回"但我一直在打边缘案件。这个问题类似于找到某个整数的下一个最大倍数的概括。
到目前为止我的尝试(runnable link:https://ideone.com/AhXG5M):
#include <iostream>
using namespace std;
using uint32 = unsigned long;
uint32 NextLargest(int width, int offset, uint32 mask, uint32 pattern, uint32 val) {
unsigned long long ret = (val + 1) & ~mask;
if ((ret & ((1 << (offset + 1)) - 1)) == 0) {
// "carry" across the mask
ret += 1 << (offset + width);
}
return ret | pattern;
}
int main() {
// your code goes here
int width = 12;
int offset = 4;
uint32 significant_bits = (1 << (width + 1) - 1) << offset;
uint32 wanted_bits = 0xFFF << offset;
cout << hex;
// want 0xFFF1 -- correct
cout << NextLargest(width, offset, significant_bits, wanted_bits, 0) << endl;
// want 0xFFF2 -- correct
cout << NextLargest(width, offset, significant_bits, wanted_bits, 1) << endl;
// want 0x1FFFF0 -- incorrect, get 0xFFF0
cout << NextLargest(width, offset, significant_bits, wanted_bits, 0xF) << endl;
return 0;
}
答案 0 :(得分:3)
我没有对此进行测试,但以下算法应该有效(伪代码):
let mask, pattern, and val be inputs
let fls be function that finds last bit set in word
let ffs be function that finds first bit set in a word
let applied be (val & ~mask) | pattern
if applied is greater than val then
return applied
let low_order_mask be (1 << ffs(mask)) - 1
if applied == val then
let flipped_low be (~value & low_order_mask)
if not flipped_low then
return applied + 1 // no need to carry
// need to carry
let set_low_zero be applied & ~low_order_mask
let carry be 1 << (fls(mask) + 1)
return set_low_zero + carry
POSIX提供了 fls
和ffs
,但其他系统可能不会这样做。如果需要,有关于如何实现这些的答案。
答案 1 :(得分:1)
想想value
分为3。
掩码上方,掩码中和掩码下方的位。
H(value)
,M(value)
,L(value)
。
我们知道M(result)==pattern
。
我们有三位候选人。
C1是H(value)+pattern+0
。
C2是H(value)+pattern+L(value)+1
C3为H(value)+pattern+X
X==(mask<<1)&~mask
。这是mask
以上的最低位。
如果pattern>M(value)
我们可以使用C1。
减少高位将得到一个数字<value
,设置任何低位都会增加数字。
如果pattern==M(value)
,我们可以尝试实际上value+1
的C2。
如果向模式位添加一个溢出,则会失败。
这意味着所有低位都被设置,下一个要添加的最低位是掩码上方的第一位。
unsigned next_masked(unsigned mask,unsigned pattern,unsigned value){
unsigned reduced_pattern=(mask&pattern);//May not be required...
unsigned over_add=(mask<<1)&~mask;
unsigned upper_mask=~(over_add-1);
unsigned cand=(value&upper_mask)|reduced_pattern;
if(cand>value){
return cand;
}
if((value&mask)==reduced_pattern){
unsigned scand=value+1;
if((scand&mask)==reduced_pattern){
return scand;
}
}
return cand + over_add;
}
这里再次进行一些单元测试:
#include <iostream>
unsigned next_masked(unsigned mask,unsigned pattern,unsigned value){
unsigned reduced_pattern=(mask&pattern);//May not be required...
unsigned over_add=(mask<<1)&~mask;
unsigned upper_mask=~(over_add-1);
unsigned cand=(value&upper_mask)|reduced_pattern;
if(cand>value){
return cand;
}
if((value&mask)==reduced_pattern){
unsigned scand=value+1;
if((scand&mask)==reduced_pattern){
return scand;
}
}
return cand + over_add;
}
bool invariant_next_masked(unsigned mask,unsigned pattern,unsigned value,unsigned result){
if((result&mask)!=(pattern&mask)){
return false;
}
if(result<=value){
return false;
}
for(unsigned test=result-1;test>value;--test){
if((test&mask)==(pattern&mask)){
return false;
}
}
return true;
}
int check_next_masked(unsigned mask,unsigned pattern,unsigned value,unsigned expect){
unsigned result=next_masked(mask,pattern,value);
if(result!=expect){
std::cout << std::hex << mask << ' ' << std::hex << pattern << ' ' << std::hex <<value << "==" << std::hex <<result << "!=" << std::hex <<expect <<'\n';
return 1;
}
if(!invariant_next_masked(mask,pattern,value,result)){
return 1;
}
return 0;
}
int main() {
int errors=0;
errors+=check_next_masked(0xFF00,0x0100,0x0000,0x00100);
errors+=check_next_masked(0xFF00,0x0100,0x00FF,0x00100);
errors+=check_next_masked(0xFF00,0x0100,0x10FE,0x10100);
errors+=check_next_masked(0xFF00,0x0100,0x1067,0x10100);
errors+=check_next_masked(0xFF00,0x0100,0x10123,0x10124);
errors+=check_next_masked(0xFF00,0x0100,0x110FF,0x20100);
errors+=check_next_masked(0xFF00,0x0100,0x102FF,0x20100);
errors+=check_next_masked(0xFF00,0x0100,0x101FF,0x20100);
errors+=check_next_masked(0x000F,0x0007,0x10123,0x10127);
errors+=check_next_masked(0x000F,0x0007,0x10128,0x10137);
errors+=check_next_masked(0x0FF0,0x0230,0x10128,0x10230);
errors+=check_next_masked(0x0FFF0,0x01230,0x01231,0x01232);
errors+=check_next_masked(0x0FFF0,0x01230,0x41237,0x41238);
errors+=check_next_masked(0x0FFF0,0x01230,0x4123F,0x51230);
if(errors>0){
std::cout << "Errors "<< errors << '\n';
return 1;
}
std::cout << "Success\n";
return 0;
}
答案 2 :(得分:0)
是计算 LARGEST 或 SMALLEST 下一个值的问题?最大的值似乎很奇怪。如果要求是计算最小值,我认为这段代码应该有效:(在gcc 7.1上测试,假设64位目标,sizeof(void *)== sizeof(size_t)== sizeof(uint64_t))
size_t next_smallest_value (size_t mask, size_t pattern, size_t x) {
assert(pattern & mask == pattern);
// only change bits within mask range to meet the requirement
auto y = x & ~mask | pattern;
if (y > x) {
// if the operation increased the value
// mask off all the lower bits
auto lsb_mask = __builtin_ctzll(mask);
return y & ~ones(lsb_mask);
} else {
// otherwise, the operation decreased or didn't change the value
// need to increase the fraction higher than the mask
auto msb_mask = 63 - __builtin_clzll(mask);
// higher part cannot be empty if the masked part decrease
assert(msb_mask < 63);
auto higher = ((y >> msb_mask) + 1) << msb_mask;
// also higher part cannot overflow
assert(higher != 0);
return y & mask | higher;
}
}
这个想法非常简单:将位分为3个部分:高部分,屏蔽部分,下部分。被遮罩的部分可以直接从mask
和pattern
推导出来,并且由---
- name: sorting json
hosts: localhost
tasks:
- name:
uri:
url: http://jsonplaceholder.typicode.com/users
method: GET
return_content: yes
register: result
ignore_errors: yes
- debug: msg="{{result.content}}"
和 {
"address": {
"city": "Gwenborough",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
},
"street": "Kulas Light",
"suite": "Apt. 556",
"zipcode": "92998-3874"
},
"company": {
"bs": "harness real-time e-markets",
"catchPhrase": "Multi-layered client-server neural-net",
"name": "Romaguera-Crona"
},
"email": "Sincere@april.biz",
"id": 1,
"name": "Leanne Graham",
"phone": "1-770-736-8031 x56442",
"username": "Bret",
"website": "hildegard.org"
},
确定,它不能是其他值。
在计算屏蔽位后,如果值增加,只需屏蔽下部的所有位。否则,将高位增加1(并且还屏蔽所有低位)。
上面的代码没有处理格式错误的输入,它会触发断言,但检查不会用尽。
答案 3 :(得分:0)
这个有点令人困惑的问题有两个功能 第一个函数提供满足结果要求的最大下一个整数。 第二个给出了下一个SMALLEST值。
1:获取满足result & mask == pattern
和result > val
的最大整数:
unsigned NextLargest (unsigned mask, unsigned pattern, unsigned val) {
// zero "mask" bits and set "pattern" bits in largest (unsigned) int
unsigned const x = ~mask | pattern;
// if result is not greater than val, we can't satisfy requirements
if (x <= val) {
... report error, return error code or throw something
}
return x;
}
显然,这只返回符合要求result & mask == pattern
和result > val
的最高(无符号)整数值。 if子句检查结果是否不会大于val
,函数将失败。
2:在符合要求的val
之后获取最小的下一个值:
unsigned NextSmallest (unsigned mask, unsigned pattern, unsigned val) {
unsigned const x = (val + mask + 1) & ~mask | pattern;
if (x <= val) {
... increment wrapped, can't give greater value
}
return x;
}
修改:将(val|mask)
更改为val+mask
,因为结果必须仍然大于val
。
此函数计算val + 1
并在mask
&bit; d位上传送溢出位。
以下是该函数的一些示例,如mask = 0x0ff00
和pattern = 0x00500
:
val +mask +1 &~mask |pattern == result
0x00000 0x0ff00 0x0ff01 0x00001 0x00501
0x00001 0x0ff01 0x0ff02 0x00002 0x00502
0x000fe 0x0fffe 0x0ffff 0x000ff 0x005ff
0x000ff 0x0ffff 0x10000 0x10000 0x10500
0x00100 0x10000 0x10001 0x10001 0x10501
0x0f000 0x1ef00 0x1ef01 0x10001 0x10501
0x0ff00 0x1fe00 0x1fe01 0x10001 0x10501
0x0ffff 0x1feff 0x1ff00 0x10000 0x10500
0x10000 0x1ff00 0x1ff01 0x10001 0x10501
0x10001 0x1ff01 0x1ff02 0x10002 0x10502
0x100ff 0x1ffff 0x20000 0x20000 0x20500
经过长时间的编辑和重写,我仍然无法为这个问题提供足够好的答案。它的例子有很奇怪的结果。如果有人发现这些功能或部分功能有用,我仍然会留在这里。另外,我实际上没有测试过计算机上的功能。