纯粹的基础变革

时间:2013-01-02 06:54:50

标签: c++ math numbers

我正在尝试(没有太大成功)编写一个简短的c ++函数:

双位数(double x,int b,int d)

返回数字x的base-b扩展中的第d个数字,可以是正数或负数,也可以是分数。当d为负数时,它应该返回十进制小数点后的数字(对于d = 0,它的欠定义,所以说它在这种情况下返回0)。 例如:

    const double x = 25.73;
    for (int n = -5; n <= 5; n++)
            cout<<digit(x,10,n)<<' ';

应该打印: 0 0 0 3 7 0 五 2 0 0 0

该函数必须只使用循环,if,exp,pow,log,floor和ceil。即没有sprintf技巧等。

感谢!!!

编辑:为简单起见,假设2 <= b <= 10

编辑:请同时避免使用mod,只使用基于pow-exp-log-floor-ceil的解决方案

2 个答案:

答案 0 :(得分:2)

这似乎是最直接的实现,它似乎工作正常。

int digit( double x, int base, int index ) {
    // shift number (mult by power of base) so desired digit is in one's place
    x = std::abs( x ) * std::pow( base, - index );
    // fmod strips higher digits; floor strips lower digits, leaving result.
    return std::floor( std::fmod( x, base ) );
}

我将返回类型从double更改为int,因为在数字中有一个分数是没有意义的。并且它不会返回.为0,因为这不是一个数字。第0位的值就是那个位置。

这也忽略了减号;你没有为负数定义“base-b扩展”。您可以调整函数以返回b的补码表示法等等。

通过替换x,您可以将其转换为一行,因此它将满足constexpr在数学函数为constexpr的平台上的要求。

答案 1 :(得分:0)

让我们分两步完成。

1.将数字转换为基数b

2.找到第d位并将其返回。

分割任务的原因是因为如果你反复调用相同的基数和数字集并且仅针对不同的d,那么我们可以将数字缓存在新的基数中。例如,以下函数转换数字<强> a 从基数10到基数 b 。我很好奇如何处理分数。

string changeBase(int a,int b)
{
  string A="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  string res="";
  while(a>=b)
  {
      res=A[a%b]+res;
      a=a/b;
  }
  return res;
 }

我们需要以字符串形式返回,因为新基数可以包含诸如“A”或“B”之类的数字,它们代表10,11等的剩余部分,依此类推。 然后我们可以使用返回的字符串,如:

 string A=changeBase(24,2);
 cout<<A[0];//for some d

对于否定支持,您可以根据您为负 d 定义的方式,适当地使用字符串索引。