Clojure

double division by zero inconsistency

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: Release 1.9
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Approval:
    Triaged

Description

Division by zero with doubles will throw an exception if both arguments are boxed, but not otherwise:

Clojure 1.9.0-beta1
user=> (/ 5.0 0.0)
##Inf
user=> (/ (identity 5.0) 0.0)
##Inf
user=> (/ 5.0 (identity 0.0))
##Inf
user=> (/ (identity 5.0) (identity 0.0))
ArithmeticException Divide by zero  clojure.lang.Numbers.divide (Numbers.java:163)

Activity

Hide
Erik Assum added a comment -

So, I guess some division by zero is somewhat undefined.
If one removes

if(yops.isZero((Number)y))
	    throw new ArithmeticException("Divide by zero");

then

(/ (identity 5.0) (identity 0.0))

returns infinity as the unboxed versions.

Although doing so, also causes a change to

(/ 5 0)

which then becomes `1/0`, whereas it previously threw Divide by zero.

From Numbers.java we see that unboxed math does not protect against division by zero:

static public double divide(double x, double y){
	return x / y;
}

whereas boxed versions do:

static public Number divide(Object x, Object y){
	if (isNaN(x)){
		return (Number)x;
	} else if(isNaN(y)){
		return (Number)y;
	}
	Ops yops = ops(y);
	if(yops.isZero((Number)y))
		throw new ArithmeticException("Divide by zero");
	return ops(x).combine(yops).divide((Number)x, (Number)y);
}

This inconsistency is also reproducible with clojure 1.8:

Clojure 1.8.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_144-b01
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> (/ 5.0 0.0)
Infinity
user=> (/ (identity 5.0) (identity 0.0))

ArithmeticException Divide by zero  clojure.lang.Numbers.divide (Numbers.java:158)
user=>
Show
Erik Assum added a comment - So, I guess some division by zero is somewhat undefined. If one removes
if(yops.isZero((Number)y))
	    throw new ArithmeticException("Divide by zero");
then
(/ (identity 5.0) (identity 0.0))
returns infinity as the unboxed versions. Although doing so, also causes a change to
(/ 5 0)
which then becomes `1/0`, whereas it previously threw Divide by zero. From Numbers.java we see that unboxed math does not protect against division by zero:
static public double divide(double x, double y){
	return x / y;
}
whereas boxed versions do:
static public Number divide(Object x, Object y){
	if (isNaN(x)){
		return (Number)x;
	} else if(isNaN(y)){
		return (Number)y;
	}
	Ops yops = ops(y);
	if(yops.isZero((Number)y))
		throw new ArithmeticException("Divide by zero");
	return ops(x).combine(yops).divide((Number)x, (Number)y);
}
This inconsistency is also reproducible with clojure 1.8:
Clojure 1.8.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_144-b01
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> (/ 5.0 0.0)
Infinity
user=> (/ (identity 5.0) (identity 0.0))

ArithmeticException Divide by zero  clojure.lang.Numbers.divide (Numbers.java:158)
user=>
Hide
Erik Assum added a comment -

Any thoughts on an approach?
Both throwing on division by zero for natives and allowing it for boxed seems to be a serious change, and the tests expects an exception for boxed division by zero.

Show
Erik Assum added a comment - Any thoughts on an approach? Both throwing on division by zero for natives and allowing it for boxed seems to be a serious change, and the tests expects an exception for boxed division by zero.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated: