There's a couple things going wrong here.
For starters, what you want to do is find each valid textual representation of a number in the input box. This is a bit trickier than it sounds - do you want to support negative numbers? Decimal places?
Enter the Regular Expression, one of the most useful inventions in the history of programming. Using a regular expression one can, without too much difficulty, extract all the valid numeric sequences from strings like abc-.02dflaxoe042xne+3.14-5
( -0.2
, 042
, +3.14
, and -5
, that is - all of which can be parsed by parseFloat
individually.
This regex does the trick:
/[-+]?(\d+(\.\d+)?|\.\d+)/g
It matches an optional leading -
or +
( [-+]?
), followed by either
\d+(\.\d+)?
: one or more decimal number 0-9 (\d
) followed optionally by a decimal point (\.
)and one or more decimal numbers
or
- a decimal point
\.
followed by one or more decimal numbers
The first case matches +3.2, -31, -0.0001, 51, or 42 - the second matches .2, -.1, or +.31. That second case is a bit unusual (no decimal numbers before the decimal point ) but since parseFloat
could read them I added them in.
Some might argue that there's a simpler way to write this - I do wish I could combine the either/or, but I couldn't figure out a better regex that made sure that at least one numeric character was supplied. Edits welcome.
The parsing trick, trick, as you were approaching, is to parse out all the numeric substrings first, then parse each into a floating point number and compare. You had some of the right ideas, but there were still some things missing.
Math.max()
takes one or more numeric arguments, but can't take an array, unfortunately. It would make a lot of sense if it could, but it can't. I didn't try to find a way around this, though there might be one, because I had to parse each of the numeric strings anyway, I just took max()
out completely and used the >
operator instead.
A general programming point now: when you're looking for the greatest, don't make assumptions like starting the search at 0. In your example, if no numbers are supplied, or all negative numbers, then the greatest number is your starting point of 0
- which the user may not even have inputted. I initialized my greatest
to undefined
and then handled that case below.
A bit of further help:
var button = document.getElementById("greatestbutton");
button.onclick = function greaterNumber() {
is a long way of using a variable to say
document.getElementById("greatestbutton").onclick = function greaterNumber() {
You'll notice that you have both the output <span>
and the <input>
field ( which should end with />
, by the way) with an id
of numbers
- you can't refer to two elements with the same ID of course.
Finally, a semantic point ( :-) ): As a believer in the semantic principles of markup, I'll ask you to avoid all-too-common anti-patterns such as <div id="greatestbutton" class="button">
. There is already a <button>
tag, and users will be told it's a button even if they're on a braille terminal or other such devices - a <div class='button'>
loses this semantic meaning regardless of how pretty you make it with CSS. For the same reason, I replaced your <span>
with a <kbd>
tag ( for "typed input").
Here's what I came up with:
<script type='text/javascript'>
greaterNumber = function () {
var array = document.getElementById('numbers').value.match(/[-+]?(\d+(\.\d+)?|\.\d+)/g)
alert(array)
if (!array || array.length <= 0) return; // no numbers at all!
var greatest = undefined
if (array.type == 'number') // only one number
array = [array] // convert to array for simplicity
for (var i in array) {
array[i] = parseFloat(array[i])
if (greatest == undefined || array[i] > greatest) greatest = array[i]
}
document.getElementById('greatest').innerHTML = greatest;
}
</script>
</head>
<body>
<p>
<label for="numbers">Enter numbers seperated by a space:</label>
<input type="text" size="20" id="numbers" />
</p>
<p>
<button id="greatestbutton" onclick="greaterNumber()">Click here to get the Greatest Number!</button>
</p>
<div>The greatest number is in the alert box: <kbd id="greatest">?</kbd>
</div>
</html>
See a working example here: http://jsfiddle.net/7JN74/10/