Reputation: 399
I'm trying (without much success) to write a short c++ function:
double digit(double x, int b, int d)
that returns the d-th digit in base-b expansion of the number x, which can be positive or negative, and can be a fraction. when d is negative, it should return the after-the-decimal-dot digits (its underfined for d=0 so say it returns 0 in that case). For example:
const double x = 25.73;
for (int n = -5; n <= 5; n++)
cout<<digit(x,10,n)<<' ';
should print: 0 0 0 3 7 0 5 2 0 0 0
The function must use only loops, if, exp, pow, log, floor and ceil. i.e., without sprintf tricks etc.
Thanks!!!
EDIT: For simplicity, assume 2<=b<=10
EDIT: Please also avoid using mod, only pow-exp-log-floor-ceil based solutions
Upvotes: 0
Views: 401
Reputation: 137830
This seems to be the most straightforward implementation, and it seems to work just fine.
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 ) );
}
I changed the return type from double
to int
since it doesn't make sense to have a fraction in a digit. And it doesn't return .
for 0, because again that's not a digit. The 0'th place value is the one's place.
Also this ignores the minus sign; you didn't define the "base-b expansion" for negative numbers. You could adjust the function to return b's complement notation or whatever.
By substituting x
you can make this into one line, so it will satisfy the requirements for constexpr
on platforms where the math functions are constexpr
as well.
Upvotes: 2
Reputation: 3179
Let's do this in two steps.
1.Convert a number to base b
2.Find the d-th digit and return it.
The reason for splitting the tasks is because if you are repeatedly calling for the same set of base and number and only for different d's, then we can cache the number in the new base.For example the following function converts a number a from base 10, to a base b.I am curious how to deal with fractions.
string changeBase(int a,int b)
{
string A="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string res="";
while(a>=b)
{
res=A[a%b]+res;
a=a/b;
}
return res;
}
We need to return as a string as the new base can have digits like 'A' or 'B' or the like, which represent remainders of 10, 11, and so on. Then we can play around with the returned string as in:
string A=changeBase(24,2);
cout<<A[0];//for some d
For negative support you can use the string index appropriately based on how you define it for negative d.
Upvotes: 0