Converting base N to base 10

7 visualizaciones (últimos 30 días)
Yiting Jin
Yiting Jin el 29 de Nov. de 2021
Editada: John D'Errico el 29 de Nov. de 2021
The question quest us to write a function BaseNBase10 that has two inputs: 1) a string representation of a number (positive integer) in base N ; 2) the base of the number. The function returns the equivalent number in base 10 (scalar).
However, when I run my test case for base 16, it can not read in letter as a part of the vector. What should I do so this function can run with a string input and a number output.
writeCodeToTestMyCode;
function writeCodeToTestMyCode
% disp(strcat("Expected: 10 and Actual: ", num2str(bbaseNtobase10("1010",2))));
% disp(strcat("Expected: 157 and Actual: ", num2str(bbaseNtobase10("235",8))));
disp(strcat("Expected: 693 and Actual: ", num2str(basse10tobaseN("2B5",16))));
end
function [base10number] = bbaseNtobase10(baseNnumber,baseN)
workingnumber = num2str(flip(baseNnumber));
valueinbase10 = 0;
finalvalue = 0;
if baseN == 16
for j = 1:length(workingnumber)
if strcmp(workingnumber(i), "A") == 1
workingnumber(i) = 10;
elseif strcmp(workingnumber(i), "B") == 1
workingnumber(i) = 11;
elseif workingnumber(i) == C
workingnumber(i) = 12;
elseif workingnumber(i) == D
workingnumber(i) = 13;
elseif workingnumber(i) == E
workingnumber(i) = 14;
else workingnumber(i) = 15;
end
end
end
for i = 1:length(workingnumber)
valueinbase10 = workingnumber(i) * (baseN^(i-1));
finalvalue = finalvalue + valueinbase10;
end
base10number = finalvalue;
end

Respuesta aceptada

John D'Errico
John D'Errico el 29 de Nov. de 2021
Editada: John D'Errico el 29 de Nov. de 2021
Why would you special case base 16 anyway?
What if they gave you base 15? Or base 19? Or base 12?
It is a really bad coding style to write it like this. Sorry, but it is. You want to write code that does not need to special case everything, else your code will be incredibly complicated, and prone to bugs that will drive you mad. SERIOUSLY. (I'm not saying this to hurt your feelings, just to explain that you want to avoid writing code like that. But new users of MATLAB tend to use all sorts of programming patterns that they will then need to unlearn to progress. This is one that I will try to help you unlearn before you ever make it a bad habit.)
So how might you do things more sanely, in a way that does not need to use a multitude of if statements, tests, etc? First, is to consider what the ascii code values for those numbers and letters are.
+'0123456789'
ans = 1×10
48 49 50 51 52 53 54 55 56 57
+'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ans = 1×26
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
This would take you as far out as base 36.
One simple idea would be to build a lookup table.
LUT = NaN(1,90);
LUT(+'0123456789') = 0:9;
LUT(+'ABCDEFGHIJKLMNOPQRSTUVWXYZ') = 10:35;
What does LUT do?
LUT(+'0')
ans = 0
It returns the number 0. Neat, huh? LUT should return what, 11 if you give it a 'b', right? A 'Z' would yield 35, just in case you are faced with base 36.
LUT(+'BZ')
ans = 1×2
11 35
Now, how might your code look? Ok, how would your code look if i was writing it?
MYbbaseNtobase10('45AB2',16)
ans = 285362
Is that correct? We can test the code using base2dec, an existing MATLAB function.
base2dec('45AB2',16)
ans = 285362
So it works. And the nice thing is, it works for any base from 2 to 36.
MYbbaseNtobase10('10101010101010101',2),base2dec('10101010101010101',2)
ans = 87381
ans = 87381
Take a read through the code below, and think about how it works. I'll add a version that is a little less sophisticated at the end.
function base10number = MYbbaseNtobase10(baseNnumber,baseN)
% handles ANY base conversion from base 2 to base 36, with output in base 10.
LUT = NaN(1,90); % putatively as preallocation, but the NaNs also serve as an error indicator
LUT(+'0123456789') = 0:9;
LUT(+'ABCDEFGHIJKLMNOPQRSTUVWXYZ') = 10:35;
% just in case they throw a curve ball, and give you lower case letters.
baseNnumber = upper(baseNnumber);
% the + converts a character string into ascii equivalents, then LUT
% converts those values into integers from the set [0:baseN-1].
baseNdigits = LUT(+baseNnumber);
% did they send in an invalid character?
if any(isnan(baseNdigits))
error('An invalid digit was enconutered')
end
% recognize that a base conversion can be viewed as a polynomial
% evaluation! That is, it uses powers of the value baseN, starting
% with the zero'th power at the right.
base10number = polyval(baseNdigits,baseN);
% Good code would worry about a number that was too large to be encoded
% as a double precision flint, thus larger than 2^53-1.
if base10number > 2^53-1
error('Number was too large, exceeding the ability for exact encoding into a double')
end
end
Could you write it using a loop? Of course. You don't need to do any of the vectorized operations as I did them. A less sophisticated code might look like SimplebbaseNtobase10. I still left in the stuff to check for some obvious problems.
function base10number = SimplebbaseNtobase10(baseNnumber,baseN)
% handles ANY base conversion from base 2 to base 36, with output in base 10.
% Strip off each digit, starting from the right end
ndigits = length(baseNnumber);
base10number = 0;
B = 1;
for ind = ndigits:-1:1
% just in case they throw a curve ball, and give you lower case letters.
chardigit = upper(baseNnumber(ind));
% ascii equivalent, then offset by '0'
% remember ascii '0' is 48, so this will yield the correct result for
% any digits between 0 and 9.
digit = chardigit - '0';
% What happens to the letters?
if digit > 9
% this maps the letters 'A:Z' into the numbers 10:36. Don't forget
% we already subtracted off 48 == +'0'. So we have:
% +'A' - '0' - 7 == 10
% the rest of the letters follow along.
digit = digit - 7;
end
% accumulate the base 10 representation
base10number = base10number + B*digit;
% up the power of baseN in B, for the next pass through the loop
B = B*baseN;
end
% Good code would worry about a number that was too large to be encoded
% as a double precision flint, thus larger than 2^53-1.
if base10number > 2^53-1
error('Number was too large, exceeding the ability for exact encoding into a double')
end
end
You could certainly use a variety of schemes to do this computation. But what I want you to see is rather than having special case tests for everything, like if 'A' then, if 'B' then, if 'C' then, etc., better is to look for patterns in what you are doing. Look for schemes that will make your code simple. And finally, if you don't understand something that I did, then test it out. Follow along in the debugger to see what happens in my code.

Más respuestas (0)

Categorías

Más información sobre Programming en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by