将74位整数转换为以31为基数

时间:2018-07-26 14:46:38

标签: c++ c++11 bigint base-conversion std-bitset

要生成UFI number,请使用大小为bitsetBigInteger。要执行UFI生成的步骤2,我需要转换此数字:

9 444 732 987 799 592 368 290
(10000000000000000000000000000101000001000001010000011101011111100010100010)

进入:

DFSTTM62QN6DTV1

通过将第一个表示形式转换为基数31并从表中获取等效字符。

#define PAYLOAD_SIZE 74
// payload = binary of 9444732987799592368290
std::bitset<PAYLOAD_SIZE> bs_payload(payload);
/*
perform modulo 31 to obtain:
12(D), 14(F), 24(S), 25(T), 25, 19, 6, 2, 22, 20, 6, 12, 25, 27, 1
*/    

是否可以在不使用外部BigInteger库的情况下对我的位集执行转换?

编辑:即使干杯,我还是完成了Table - site1.com类。 -Alf 的解决方案就像一个魅力

3 个答案:

答案 0 :(得分:3)

要获得数字的31模,只需要sum up the digits in base 32,就像计算小数的3和9模一样

unsigned mod31(std::bitset<74> b) {
    unsigned mod = 0;
    while (!b.none()) {
        mod += (b & std::bitset<74>(0x1F)).to_ulong();
        b >>= 5;
    }
    while (mod > 31)
        mod = (mod >> 5) + (mod & 0x1F);
    return mod;   
}

您可以通过像how its done here一样并行运行加法来加快模数计算。类似的技术可用于计算模3、5、7、15 ...和2 31 -1

但是,由于问题实际上是关于基本转换的,而不是标题所称的模数,因此您需要为此进行实际划分。注意1 / b为0。(1)在基b +1中,我们有

  

1/31 = 0.000010000100001000010000100001...32 = 0.(00001)32

然后可以这样计算x / 31

  

x / 31 = x * 2 -5 + x * 2 -10 + x * 2 -15 + ... < / p>

uint128_t result = 0;
while (x)
{
    x >>= 5;
    result += x;
}

由于模和除法均使用shift-by-5,因此您也可以在一个循环中将它们一起进行。

但是,这里最棘手的部分是如何正确舍入商。上面的方法适用于大多数值,除了31的倍数和2的下一个幂之间的某些值之外,我发现了一种方法,可以校正多达几千个值的结果,但尚未找到所有值的通用方法< / p>

您可以看到divide by 10by 3使用了相同的移位加法。著名的Hacker's Delight中还有更多示例经过适当取整。我没有足够的时间阅读本书,以了解它们如何实现结果校正部分,因此也许以后再讲。如果有人有任何想法,将不胜感激。

一个建议是对定点进行除法。只需将值左移,以便我们有足够的小数部分可以在以后舍入

uint128_t result = 0;
const unsigned num_fraction = 125 - 75 // 125 and 75 are the nearest multiple of 5
// or maybe 128 - 74 will also work
uint128_t x = UFI_Number << num_fraction; 

while (x)
{
    x >>= 5;
    result += x;
}
// shift the result back and add the fractional bit to round
result = (result >> num_fraction) + ((result >> (num_fraction - 1)) & 1)

请注意,您上面的结果不正确。我已经确认结果是来自Yaniv Shaked's answerWolfram alpha

CEOPPJ62MK6CPR1

答案 1 :(得分:1)

此代码似乎有效。为了保证结果,我认为您需要进行其他测试。例如。首先使用小数字,您可以直接计算结果。

编辑:哦,现在我注意到您发布了所需的结果数字,并且它们匹配。意味着它总体上不错,但仍未针对极端情况进行测试。

//////////// NetworkService.js
const networkCall = (...args) => fetch(...) // say, returns promise

//////////// thunks/core/whatever.js
import { networkCall } from 'NetworkService'

const thunk = (...args) => (dispatch, getState) => {
  dispatch(startFetch(...args))

  const componentData = args
  // I'd suggest using selectors here to pick only required data from store's state
  // instead of passing WHOLE state to network layer, since it's a leaking abstraction
  const storeData = getState()

  networkCall(componentData, storeData)
    .then(resp => dispatch(fetchOk(resp)))
    .catch(err => dispatch(fetchFail(err)))
}

//////////// Component.js
import { thunk } from 'thunks/core/whatever'

const mapDispatchToProps = {
  doSomeFetch: thunk,
}

const Component = ({ doSomeFetch }) =>
  <button onClick={doSomeFetch}>Do some fetch</button>

// store.subscribe via `connect` from `react-redux`
const ConnectedComponent = connect(..., mapDispatchToProps)(Component)

MinGW g ++的结果:

Original     : 10000000000000000000000000000101000001000001010000011101011111100010100010
Reconstituted: 10000000000000000000000000000101000001000001010000011101011111100010100010
Base 31 digits (msd to lsd order): 12 14 24 25 25 19 6 2 22 20 6 12 25 27 1
Mod 31 = 1

答案 2 :(得分:0)

我没有编译伪代码,但是您可以对如何转换数字有全面的了解:

// Array for conversion of value to base-31 characters:
char base31Characters[] = 
{
    '0',
    '1',
    '2',
    ...
    'X',
    'Y'
};

void printUFINumber(__int128_t number)
{
    string result = "";
    while (number != 0)
    {
        var mod = number % 31;
        result = base31Characters[mod] + result;
        number = number / 31;
    }
    cout << number;
}