Non-decimal radices/Input: Difference between revisions

From Rosetta Code
Content added Content deleted
(Forth)
(added perl)
Line 29: Line 29:
<lang java>Integer number = Integer.valueOf(stringNum, base);</lang>
<lang java>Integer number = Integer.valueOf(stringNum, base);</lang>
The base here has the same restrictions as the <tt>Scanner</tt> example. A similar method is available in the <tt>Long</tt> class. Use no second argument for base 10.
The base here has the same restrictions as the <tt>Scanner</tt> example. A similar method is available in the <tt>Long</tt> class. Use no second argument for base 10.

=={{header|Perl}}==
The <tt>hex()</tt> function parses hexadecimal strings. The <tt>oct()</tt> function parses octal strings, as well as hexadecimal, octal, or binary strings with the appropriate prefix ("0x", "0", and "0b", respectively).
<lang perl>my $dec = "0123459";
my $hex_noprefix = "abcf123";
my $hex_withprefix = "0xabcf123";
my $oct_noprefix = "7651";
my $oct_withprefix = "07651";
my $bin_withprefix = "0b101011001";

print 0 + $dec, "\n"; # => 123459
print hex($hex_noprefix), "\n"; # => 180154659
print hex($hex_withprefix), "\n"; # => 180154659
print oct($hex_withprefix), "\n"; # => 180154659
print oct($oct_noprefix), "\n"; # => 4009
print oct($oct_withprefix), "\n"; # => 4009
print oct($bin_withprefix), "\n"; # => 345
# nothing for binary without prefix
</lang>


=={{header|Ruby}}==
=={{header|Ruby}}==

Revision as of 21:46, 9 June 2009

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.

Forth

Arbitrary base 2-36 parsing is supported by the same mechanism as decimal parsing: set the user variable BASE to the desired base, then scan the number. There are two convenience words for setting the base to DECIMAL or HEX. <lang forth>

parse# ( str len -- u true | false )
  0. 2SWAP DUP >R >NUMBER NIP NIP 
  R> <> DUP 0= IF NIP THEN ;
base# ( str len base -- u true | false )
 BASE @ >R  BASE !  parse#  R> BASE ! ;

</lang>

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 (obviously, the default is 10): <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. Use no second argument for base 10.

Perl

The hex() function parses hexadecimal strings. The oct() function parses octal strings, as well as hexadecimal, octal, or binary strings with the appropriate prefix ("0x", "0", and "0b", respectively). <lang perl>my $dec = "0123459"; my $hex_noprefix = "abcf123"; my $hex_withprefix = "0xabcf123"; my $oct_noprefix = "7651"; my $oct_withprefix = "07651"; my $bin_withprefix = "0b101011001";

print 0 + $dec, "\n"; # => 123459 print hex($hex_noprefix), "\n"; # => 180154659 print hex($hex_withprefix), "\n"; # => 180154659 print oct($hex_withprefix), "\n"; # => 180154659 print oct($oct_noprefix), "\n"; # => 4009 print oct($oct_withprefix), "\n"; # => 4009 print oct($bin_withprefix), "\n"; # => 345

  1. nothing for binary without prefix

</lang>

Ruby

The String class has methods to coerce a string into another form: <lang ruby>dec1 = "0123459" hex2 = "abcf123" oct3 = "7651" bin4 = "101011001"

dec1.to_i # => 123459 hex2.hex # => 180154659 oct3.oct # => 4009

  1. nothing for binary</lang>

The Integer class can parse a string, provided the string has the right prefix: <lang ruby>Integer(dec1) # => ArgumentError: invalid value for Integer: "0123459" Integer(dec1.sub(/^0+/,"")) # => 123459 Integer("0x" + hex2) # => 180154659 Integer("0" + oct3) # => 4009 Integer("0b" + bin4) # => 345</lang>

And then there's the poorly documented Scanf module in the Ruby stdlib, that seems to wrap the matched value in an array: <lang ruby>require 'scanf' dec1.scanf("%d") # => [123459] hex2.scanf("%x") # => [180154659] oct3.scanf("%o") # => [4009]

  1. no scanf specifier for binary numbers.</lang>
Translation of: Tcl

<lang ruby>def scanbase(str, base)

 res = 0
 digits = %w{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}
 str.to_s.downcase.each_char do |c|
   idx = digits[0,base].find_index(c)
   idx.nil? and raise ArgumentError, "invalid base-#{base} digit: #{c}"
   res = res * base + idx
 end
 res

end

scanbase 255, 19 # => 822 scanbase dec1, 8 # => ArgumentError: invalid base-8 digit: 9</lang>

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 [lrange $digits 0 [expr {$base - 1}]] $char]
     if {$value < 0} {error "bad digit $char"}
     set res [expr {$res*$base + $value}]
  }
  return $res

}</lang> Example:

% scanbase 255 19
822
% scanbase $dec1 8
bad digit 9