View Full Version : I don't understant how this script works
shlagish
04-30-2003, 02:08 AM
I've found a script (I think it is on javascriptKit.com) that converts any number from any base (2 to 36) TO any base (2 to 36)
I don't quite understand the script. I don't see what exactly it does...
What I'm looking for is for someone to read the script to me. In other words, instead of saying "var a=10" I want someone to say: we now assing 10 to the variable "a"
This is the script:
<html>
<head>
<script language="JavaScript">
convertBase="0123456789abcdefghijklmnopqrstuvwxyz";
function convert(input,origin,dest)
{
input=input.toString().toLowerCase(); origin=origin.toString();
dest=dest.toString()
var b=0;
var Result="";
if (origin>convertBase.length || dest>convertBase.length || origin<2 || dest<2) return "Invalid numbering system"
for (var c=1;c<=input.length;c++) { b=b+convertBase.indexOf(input.substring(c-1,c))*(Math.pow(origin,input.length-c)); if (convertBase.indexOf(input.substring(c-1,c)) > origin) return 'Character "'+input.substring(c-1,c)+'" not present in origin system'; }
var a=Math.floor(Math.log(b)/Math.log(dest))
while (a>-1) {
var e=Math.pow(dest,a)
a--;
var d=(b-b%e)/e+1;
b%=e;
Ciffer=convertBase.substring(d-1,d);
Result+=Ciffer;
}
return Result
}
</script>
<form>
<table><tr>
<td colspan="2"><b>Numbers converter</b><br><small>Converts numbers between different numbering scales<br>Please input the relevant information in the boxes</small></td>
</tr>
<tr height="1"><td colspan="2" bgcolor="black"></td></tr>
<tr>
<td>Number to convert:<br><small>May hold numbers as well as letters</small></td>
<td><input type="text" name="originalNumber"></td>
</tr>
<tr height="1"><td colspan="2" bgcolor="gray"></td></tr>
<tr>
<td>Scale to convert from:<br><small>Fx. 2 for binary or 16 for hexadecimal<br>min. 2, max. <script>document.write(convertBase.length)</script></small></td>
<td><input type="text" name="originalScale"></td>
</tr>
<tr height="1"><td colspan="2" bgcolor="gray"></td></tr>
<tr>
<td>Scale to convert to:</td>
<td><input type="text" name="destinationScale"></td>
</tr>
<tr height="1"><td colspan="2" bgcolor="gray"></td></tr>
<tr>
<td><input type="button" onClick='destinationNumber.value=convert(originalNumber.value,originalScale.value,destinationScale.v alue)' value="Convert"></td>
<td><input type="text" name="destinationNumber"></td>
</tr></table>
</form>
</body>
</html>
I hope you guys know what I mean when I say "read the script".
Thanks in advance
liorean
04-30-2003, 02:36 AM
Yuck... that's too complicated a way to do an easy thing like this. It can be simplified to:
function convert(sNumber, iOldRadix, iNewRadix){
return parseInt(sNumber,
iOldRadix||10).toString(iNewRadix||10);
}
Or, you can put it as a method on any string:
String.prototype.convert=function (iOldRadix, iNewRadix){
return parseInt(this,
iOldRadix||10).toString(iNewRadix||10);
}
liorean
04-30-2003, 03:04 AM
Originally posted by shlagish
I've found a script (I think it is on javascriptKit.com) that converts any number from any base (2 to 36) TO any base (2 to 36)
I don't quite understand the script. I don't see what exactly it does...
What I'm looking for is for someone to read the script to me.
I hope you guys know what I mean when I say "read the script".
I didn't do it that very thoroughly (could have gone into much beter detail when it comes to the mathematical actions) but I hope this will explain it to you:
convertBase="0123456789abcdefghijklmnopqrstuvwxyz";
Set up the string of characters in maximum radix (36).
function convert(input,origin,dest){
Declare a function called convert that takes three arguments: a string or number representing original number, the radix we're converting from and the radix we're converting to.
input=input.toString().toLowerCase();
Make sure input it's a string that's lowercase.
origin=origin.toString();
Make sure original radix is a string.
dest=dest.toString()
Do the same for destination radix
var b=0;
Declare variable to hold decimal number
var Result="";
Declare variable to contain the result.
if (origin>convertBase.length || dest>convertBase.length || origin<2 || dest<2)
If input/output radixes are not within the range 2...36
return "Invalid numbering system"
Return this string
Otherwise:
for(var c=1;c<=input.length;c++){
For each character in the input string do the following:
b=b+convertBase.indexOf(input.substring(c-1,c))*(Math.pow(origin,input.length-c));
Determine the numerical value of that character and multiply by the origin radix raised to the character's position in the input.
if (convertBase.indexOf(input.substring(c-1,c)) > origin)
If character is above radix...
return 'Character "'+input.substring(c-1,c)+'" not present in origin system';
Return this string.
}
End of loop.
var a=Math.floor(Math.log(b)/Math.log(dest))
Determine how many characters the number will take in the destination radix. (Logarithms used this way provide just that.)
while (a>-1) {
While that number is larger than -1 do:
var e=Math.pow(dest,a)
Set e to the destination radix raised to the position on the to-be character in the result string.
a--;
Decrement position in string
var d=(b-b%e)/e+1;
Determine the numerical valie of the character to be written in this position
b%=e;
Remove that number from decimal number.
Ciffer=convertBase.substring(d-1,d);
Determine the actual character that represents that value
Result+=Ciffer;
And add it to the result
}
End of loop
return Result
Return the resulting string
}
End function.
liorean
04-30-2003, 03:11 AM
parseInt takes any type of argument, and if it can be interpreted as an integer, it will do so. It takes a radix as second argument, if radix is different from the default decimal (10).
variable.toString turns any type of variable to a string. If it's a number, it takes an argument of the radix you want it to write the number in.
shlagish
04-30-2003, 03:27 AM
b=b+convertBase.indexOf(input.substring(c-1,c))*(Math.pow(origin,input.length-c));
Determine the numerical value of that character and multiply by the origin radix raised to the character's position in the input.
raised to the character's position... How does it do this. I don't understant why there is a exponant in here
var a=Math.floor(Math.log(b)/Math.log(dest))
Determine how many characters the number will take in the destination radix. (Logarithms used this way provide just that.)
Do you mind explaining why and how it does this?
var e=Math.pow(dest,a)
Set e to the destination radix raised to the position on the to-be character in the result string.
I don't quite know how it raises e to the position on the to-be character... etc
var d=(b-b%e)/e+1;
Determine the numerical value of the character to be written in this position
How does this work?
b%=e;
Remove that number from decimal number.
Wouldn't floor() work?
Next:
I don't know what parseInt means, therefore, I can't understand what :
parseInt(sNumber,
iOldRadix||10).toString(iNewRadix||10);
does.
Thanks, sorry to take so much of your time, I'm not very good at javascript yet.
liorean
04-30-2003, 03:03 PM
Let's begin with some number theory:
We have a number 1234.
q: What is the position of each character?
a: in 1234 the positions are
3210, since integers are built with the zero end to the right.
In a string, zero end is to the left.
We know that the value of each of those characters depends
on it's position:
4: 4*1
3: 3*10=30
2: 2*100=200
1: 1*1 000=1 000
q: Now, that's if they are in decimal. What if they are
quintary (a radix of 5)? (calculations in decimal)
a: 4: 4*1
3: 3*5=15
2: 2*25=50
1: 1*125=125
So, 1234 can represent either 125+50+15+4=194 in radix 5
or 1 234 in radix 10, or some other value in other radices.
Did you see a pattern in there, in how the character value was calculated?
If not, here you are:
4: 4*10^0=4
3: 3*10^1=30
2: 2*10^2=200
1: 1*10^3=1 000
Or quintary:
4: 4*5^0=4
3: 3*5^1=15
2: 2*5^2=50
1: 1*5^3=125
Now, did you see a pattern in that, something that can let us
write one general form instead of one for each radix?
4: 4*radix^positon
3: 3*radix^positon
2: 2*radix^positon
1: 1*radix^positon
And, the last generalisation we'll do:
(new colour code added for explaining things from this)
character value: character*(radix^position)
q: What was that good for?
a: It explains
b=b+convertBase.indexOf(input.substring(c-1,c))*
(Math.pow(origin,input.length-c));.
q: How in earth does it explain that?
convertBase.indexOf() gets the position
of the character in the character set - this is equal
to finding out it's decimal representation.
Math.pow(a,b) is JavaScript's way of raising a
to the power of b.
input.length-c here converts the string position of the character to the numerical position of it.
First question answered - on to the next one
q: If I have a number value, how do I determine the number of characters
that I will need to represent it in a given radix?
a: Remember
character value: character*(radix^position)?
Here we want to do the opposite...
multiplier=radix^position
position=logradix(multiplier)
q: But we have no logradix function in our language?
How do we solve this?
a: A logarithm can always be described in any other logarithm by the formula:
logradix(value)=ln(value)/ln(radix)
q: But we want to know the number of characters needed to represent
a number in a radix... how?
a: My, you are demanding... what we will have to do here,
is to take the integer part of the radix logarithm
of the number we want to write in that radix. Like this:
position=Math.floor(Math.log(number)/Math.log(radix))
Didn't that explain your second question?
Third question is still out there...
q: So, we have the position of the character
and the whole number - how do we know what character to write?
a: What we have to do:
1. Determine the multiplier (radix^multiplier)
2. Determine the character value by taking the number, and
removing the modulo of number/multiplier, and dividing that
number with the multiplier.
3. Determine what character that character value represents.
4. Append that to the resulting string
q: How to we do those?
a: 1. var e=Math.pow(dest,a)
2. var d=(b-b%e)/e+1;
3. Ciffer=convertBase.substring(d-1,d);
4. Result+=Ciffer;
q: But that was only one character - what do we have to do to determine
all characters?
a: Loop those four actions, and in each repetition after using them,
set number to the modulo of number divided by multiplier (number%multiplier)
and decrement the position.
Yihoo! Now there's just one question leftOriginally posted by shlagish
understand what :
parseInt(sNumber,
iOldRadix||10).toString(iNewRadix||10);does.
See my previous post, or have a look at <http://devedge.netscape.com/library/manuals/2000/javascript/1.5/reference/toplev.html#1064173>
shlagish
05-02-2003, 02:58 AM
Originally posted by liorean
a: Remember
character value: character*(radix^position)?
Here we want to do the opposite...
multiplier=radix^position
position=logradix(multiplier)
I don't understand how this is supposed to give the number of positions the final number will have...
q: But we have no logradix function in our language?
How do we solve this?
a: A logarithm can always be described in any other logarithm by the formula:
logradix(value)=ln(value)/ln(radix)
I don't understand the math behind this...
Third question is still out there...
q: So, we have the position of the character
and the whole number - how do we know what character to write?
a: What we have to do:
1. Determine the multiplier (radix^multiplier)
2. Determine the character value by taking the number, and
removing the modulo of number/multiplier, and dividing that
number with the multiplier.
I really have no clue what numer 2 means. I know that it gives the 'index' of the character to be shown in convertBase, but I don'T understand fully how it does this...
Also, I don't understand why b=%e is in there...
btw, I really apreciate what you're doing for me... I realize it's like teaching rocket science to a baby, lol.
liorean
05-02-2003, 04:37 AM
Ok - as I'm not sure what part of the calculation you're not understanding, le't try explaining both the math and the reason you can use it here:
In the parenthesised expression of character*(radix^position), we have the multiplier that times the character will give our character value.
Thus, multiplier=radix^position
If we turn this the other way around, as a logarithm is the inverse of the raising to the power of a given exponent, if we want to extract the exponent, we can take the base logarithm of the original value.
In short: a=b^c -> c=loga(b)
I hope that's clear, as I don't think I can explain it better, at least not in English (which is not my motherlanguage)
The reason it will give the position of the rightmost character in the final number? This can get tricky to explain, but let's try it.
Take the decimal number 200. Now, say we wanted to get the position of the rightmost character in the final number in a radix of 3:
position = int(log3(200)) = int(4.822736302150226) = 4
{iterate while position>-1
What is the multiplier, then?
multiplier = 3^position = 3^4 = 81
And what might the character value be, then?
Character value = character*multiplier = (the number of times 200 is evenly divisible by multiplier) = 200%multiplier = 200%81 = 2;
So, the character in position 4 is 2. Now we don't need to use the log3 any more - we can decrement the position and repeat the last 2 steps, except that we have to remove the character value from 200 first, So, let's do that:
200-multiplier*character = 200-81*2= 200-162 = 38
--position = 3
end of iteration}
Time for repeating the iteration:
1. multiplier = 3^3 = 27
2. character value = character*multiplier = 38%27 = 1
3. 38-multiplier*character = 38-27*1= 38-27 = 11
4. --position = 2
1. multiplier = 3^2 = 9
2. character value = character*multiplier = 11%9 = 1
3. 11-multiplier*character = 11-9*1= 11-9 = 2
4. --position = 1
1. multiplier = 3^1 = 3
2. character value = character*multiplier = 2%3 = 0
3. 2-multiplier*character = 2-3*0= 2-0 = 2
4. --position = 0
1. multiplier = 3^0 = 0
2. character value = character*multiplier = 2%0 = 2
3. 2-multiplier*character = 2-0*0= 2-0 = 2
4. --position = -1 (Which ends the iteration)
So, what were our character values (positions below)?
21102
43210
So, now you see it works. Why? Because the logarithm is a whole number in the cases when the first character is 1 and the rest are zero - so, if we want to know the number of characters needed for displaying a number between 1 and 10, we can take the integer part of the logarithm of the value - it will be 0. For 10 up to 100, it will be 1. And so on... (note that this is true for any radix and it's repective logarithm)
Did that explain the first question?
q. Explain logradix(value)=ln(value)/ln(radix)
Hmm, I don't know what to do to explain this, really...
lb = log2
lg = log10
Now, say we have only lg and want to write lg. Then
lb(value) = lg(value)/lg(2)
So, how to prove this is the case? Let's try with the value 10...
lb(10) = lg(10)/lg(2) = 1/(the exponent you have to raise 10 to to get the value 2) = 1/0.30102999566398114 = 3.321928094887363
In other words, the exponent that you have to raise 2 to, if you want to get the value 10, is 3.321928094887363. Let's see if it seems to be correct:
2^3 = 8
2^4 = 16
Well, 10 is between those, so it COULD be true. Let's try the actual value.
2^3.321928094887363 = 10.000000000000005
What? That's very close to ten, but not exactly ten. Why not?
The answer is simply accumulating rounding errors - I had to implement lg using ln because that's all my calculator had, you see, so there were rather many steps where some rounding might get wrong.
I hope that explains it.
It's 05:40 according to my clock, and I'm getting really sleepy - I'll take the rest tomorrow...
shlagish
05-03-2003, 04:59 AM
Thanks for taking so much time on this, I'm starting to understand...
Don't kill yourself though, you gotta sleep.
vBulletin® v3.8.2, Copyright ©2000-2012, Jelsoft Enterprises Ltd.