Hexadecimal Numbers

783 views
Skip to first unread message

ntu...@googlemail.com

unread,
Dec 6, 2007, 3:39:08 AM12/6/07
to Clojure
One small question - are hexadecimal or octal numbers supported (or
even better arbitrary bases). Also are bit operations like shifting, &
| etc. supported or planned? Sorry if I missed something obvious in
the docs but I couldn't find it.

Thanks,
ntupel

Stephen C. Gilardi

unread,
Jun 13, 2008, 10:03:07 AM6/13/08
to clo...@googlegroups.com
Rich,

I came across a problem where hex notation for integer literals would be extremely useful.  I implemented the Java syntax for hex and octal integer literals with the enclosed patch to LispReader.java.  The docs for the Reader currently say this about Number literals:

Numbers - as per Java, plus indefinitely long integers are supported, as well as ratios, e.g. 22/7.
Floating point numbers with an M suffix are read as BigDecimals.

With this patch, Clojure support for Java-style integer literals is improved:

user=> 0
0
user=> -0
0
user=> 1234
1234
user=> -1234
-1234
user=> 0x1a2b
6699
user=> -0x1a2b
-6699
user=> 0177
127
user=> -0177
-127
user=> 0178   ; octal in form, but includes a non-octal digit
java.lang.IllegalArgumentException: Invalid number: 0178
[...]

I noticed that the current svn code throws an exception if it sees a trailing decimal point on what would otherwise be an integer.  This patch ignores them instead, but could be easily modified to throw an exception as well.

I think supporting the Java "0x" and "0" prefixes on integer literals is a generally useful thing.  Please consider incorporating functionality like that of the patch into Clojure.

Thanks,

--Steve

(reviewing this for posting, I noticed that Clojure's "IllegalArgumentException" on "Invalid number" should probably be changed to its subclass "NumberFormatException" as well.)

$ svn diff
Index: src/jvm/clojure/lang/LispReader.java
===================================================================
--- src/jvm/clojure/lang/LispReader.java (revision 905)
+++ src/jvm/clojure/lang/LispReader.java (working copy)
@@ -42,7 +42,7 @@
 //static Pattern symbolPat = Pattern.compile("[:]?([\\D&&[^:/]][^:/]*/)?[\\D&&[^:/]][^:/]*");
 static Pattern symbolPat = Pattern.compile("[:]?([\\D&&[^:/]][^/]*/)?([\\D&&[^:/]][^/]*)");
 //static Pattern varPat = Pattern.compile("([\\D&&[^:\\.]][^:\\.]*):([\\D&&[^:\\.]][^:\\.]*)");
-static Pattern intPat = Pattern.compile("[-+]?[0-9]+\\.?");
+static Pattern intPat = Pattern.compile("([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|0[0-9]+)\\.?");
 static Pattern ratioPat = Pattern.compile("([-+]?[0-9]+)/([0-9]+)");
 static Pattern floatPat = Pattern.compile("[-+]?[0-9]+(\\.[0-9]+)?([eE][-+]?[0-9]+)?[M]?");
 static final Symbol SLASH = Symbol.create("/");
@@ -286,8 +286,27 @@
 
 private static Object matchNumber(String s){
  Matcher m = intPat.matcher(s);
- if(m.matches())
- return Numbers.reduce(new BigInteger(s));
+ if(m.matches()) {
+ if (m.group(2) != null)
+ return 0;
+ boolean negate = (m.group(1).equals("-"));
+ String g = m.group(3);
+ if (g != null) {
+ BigInteger dec = new BigInteger(g);
+ return Numbers.reduce(negate ? dec.negate() : dec);
+ }
+ g = m.group(4);
+ if (g != null) {
+ BigInteger hex = new BigInteger(g, 16);
+ return Numbers.reduce(negate ? hex.negate() : hex);
+ }
+ g = m.group(5);
+ if (g != null) {
+ BigInteger oct = new BigInteger(g, 8);
+ return Numbers.reduce(negate ? oct.negate() : oct);
+ }
+ return null;
+ }
  m = floatPat.matcher(s);
  if(m.matches())
  {

Rich Hickey

unread,
Jun 17, 2008, 11:45:11 AM6/17/08
to Clojure
I've added Java style hex and octal integer literals, as well as
arbitrary radix using nRnnnn, e.g. binary: 2r1010010

Thanks for the input,

Rich

Albert Cardona

unread,
Jun 17, 2008, 12:06:43 PM6/17/08
to clo...@googlegroups.com
Hi Rick,


>> I've added Java style hex and octal integer literals, as well as
>> arbitrary radix using nRnnnn, e.g. binary: 2r1010010
>>
>> Thanks for the input,

Is float notation possible?

1.0f -- throws Exception

(float 1.0) works, but it's way verbose.

If it's easy, would be very nice to have.

Albert

--
Albert Cardona
http://www.mcdb.ucla.edu/Research/Hartenstein/acardona

Rich Hickey

unread,
Jun 17, 2008, 12:30:59 PM6/17/08
to Clojure


On Jun 17, 12:06 pm, "Albert Cardona" <sapri...@gmail.com> wrote:
> Hi Rick,
>
> >> I've added Java style hex and octal integer literals, as well as
> >> arbitrary radix using nRnnnn, e.g. binary: 2r1010010
>
> >> Thanks for the input,
>
> Is float notation possible?
>
> 1.0f -- throws Exception
>
> (float 1.0) works, but it's way verbose.
>
> If it's easy, would be very nice to have.
>

I'm still thinking about that. The issue there is not just of
selecting single-precision, but also serving as a type hint, so it's
not only a reader thing.

Rich
Reply all
Reply to author
Forward
0 new messages