Non-decimal radices/Input

From Rosetta Code
Revision as of 12:16, 9 June 2009 by rosettacode>Mwn3d (Added Java)
Task
Non-decimal radices/Input
You are encouraged to solve this task according to the task description, using any language you may know.

It is common to have a string containing a number written in some format, with the most common ones being decimal, hexadecimal, octal and binary. Such strings are found in many places (user interfaces, configuration files, XML data, network protocols, etc.)

This task requires parsing of such a string (which may be assumed to contain nothing else) using the language's built-in facilities if possible. Parsing of decimal strings is required, parsing of other formats is optional but should be shown (i.e., if the language can parse in base-19 then that should be illustrated).

The solutions may assume that the base of the number in the string is known.

Java

Works with: Java version 1.5+

You must know the base that the String is in before you scan it. Create a Scanner in the usual way, but then set its radix to that base: <lang java5>Scanner sc = new Scanner(System.in); //or any other InputStream or String sc.useRadix(base); //any number from Character.MIN_RADIX (2) to CHARACTER.MAX_RADIX (36) sc.nextInt(); //read in a value</lang> Later you can call sc.reset() or sc.useRadix(10) to undo this change.

Another option using the Integer class: <lang java>Integer number = Integer.valueOf(stringNum, base);</lang> The base here has the same restrictions as the Scanner example. A similar method is available in the Long class.

Tcl

<lang tcl>package require Tcl 8.6; # For easy scanning of binary

  1. The strings to parse

set dec1 "0123459" set hex2 "abcf123" set oct3 "7651" set bin4 "101011001"

  1. Parse the numbers

scan $dec1 "%d" v1 scan $hex2 "%x" v2 scan $oct3 "%o" v3 scan $bin4 "%b" v4; # Only 8.6-specific operation; others work in all versions

  1. Print out what happened

puts "$dec1->$v1 $hex2->$v2 $oct3->$v3 $bin4->$v4"</lang> This produces this output:

0123459->123459 abcf123->180154659 7651->4009 101011001->345

For a general parser up to base 36, a little function can be written: <lang Tcl>proc scanbase {str base} {

  set res 0
  set digits {0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z}
  foreach char [split [string tolower $str] ""] {
     set value [lsearch $digits $char]
     if {$value < 0} {error "bad digit $char"}
     set res [expr {$res*$base + $value}]
  }
  return $res

}</lang> Example:

% scanbase 255 19
822