# Implement Ash's float division

Ash has a bit of an interesting float division algorithm. It's designed to never return NaN, and things like signed zero and infinity need to be handled.

How it works:

Assume the inputs are positive for the rules below. One input being negative will always result in the output being negative, and both being negative will result in a positive output.

• Zero divided by anything is 0
• Anything other than 0 divided by 0 is Infinity
• Anything other than Infinity divided by Infinity is 0
• Infinity divided by anything other than Infinity is Infinity
• Infinity divided by Infinity is 1
• All other division works as normal

I/O:

For languages with floats that support signed zero and positive/negative infinity, floats are an accepted I/O format. For others, using a string is allowed. You can use any reasonable format in this string, and you can represent the infinities with anything that can't be confused with another number (such as I, ∞, inf, or :().

Input will always be two floats in your chosen representation, and output will be a single one. Floating point errors and large numbers being represented as Infinity are allowed.

Test cases:

0 / 0                   0
0 / 1                   0
0 / 8                   0
0 / Infinity            0
0 / -0                 -0
0 / -1                 -0
0 / -8                 -0
0 / -Infinity          -0
-0 / 0                 -0
-0 / 1                 -0
-0 / 8                 -0
-0 / Infinity          -0
-0 / -0                 0
-0 / -1                 0
-0 / -8                 0
-0 / -Infinity          0
1 / 0                   Infinity
8 / 0                   Infinity
Infinity / 0            Infinity
1 / -0                 -Infinity
8 / -0                 -Infinity
Infinity / -8          -Infinity
-1 / 0                 -Infinity
-8 / 0                 -Infinity
-Infinity / 0          -Infinity
-1 / -0                 Infinity
-8 / -0                 Infinity
-Infinity / -0          Infinity
Infinity / 1            Infinity
Infinity / 8            Infinity
Infinity / -1          -Infinity
Infinity / -8          -Infinity
-Infinity / 1          -Infinity
-Infinity / 8          -Infinity
-Infinity / -1          Infinity
-Infinity / -8          Infinity
Infinity / Infinity     1
Infinity / -Infinity   -1
-Infinity / Infinity   -1
-Infinity / -Infinity   1
1 / 1                   1
1 / 8                   0.125
1 / Infinity            0
1 / -1                 -1
1 / -8                 -0.125
1 / -Infinity          -0
-1 / 1                 -1
-1 / 8                 -0.125
-1 / Infinity          -0
-1 / -1                 1
-1 / -8                 0.125
-1 / -Infinity          0
8 / 1                   8
8 / 8                   1
8 / Infinity            0
8 / -1                 -8
8 / -8                 -1
8 / -Infinity          -0
-8 / 1                 -8
-8 / 8                 -1
-8 / Infinity          -0
-8 / -1                 8
-8 / -8                 1
-8 / -Infinity          0
1 / 0.125               8
0.1 / 0.2               0.5
10 / -3                 -3.333333
1 / 0.0000000000000001  10000000000000000


Other:

This is , so shortest answer in bytes (per language) wins!

• Since it sounds like input floats can be non-integer, it would be good to have some examples of that in the test cases. And I assume if we use floats, it wouldn't be held against us if the floats overflow to infinity when the output is be too large to represent?
– xnor
Apr 9, 2021 at 18:23
• @xnor I'll add some test cases for non-integers. Overflow and floating point errors are fine. Apr 9, 2021 at 18:24
• Is [sign, positive float] a reasonable representation? Apr 9, 2021 at 18:34
• @UnrelatedString I'm going to say no, sorry. It's probably only a few bytes to turn that into the required format in most languages though. Apr 9, 2021 at 18:36
• @Wezl There's no "evaluate as ash" operator, but there is / which works fine :p Apr 9, 2021 at 18:48

x?y|isNaN$x/y=tanh x*tanh y|0<1=x/y  Try it online! The relevant function is (?), which takes two Doubles as input and returns a Double as output. ## How? The hyperbolic tangent is an amazing function (two bytes shorter than signum!). x tanh x 0.0 0.0 -0.0 -0.0 Infinity 1.0 -Infinity -1.0 # Haskell, 30 29 bytes x?y|x/y<=1/0=x/y|0<1=tanh$x*y


Try it online!

Using MarcMush's amazing trick, which relies on the well-known formula1 $$\tanh(x\cdot y)=\tanh(x)\cdot\tanh(y).$$

1 I know, I know, maths.

• Not gonna lie this is probably the first time I've ever seen someone use any of the hyperbolic trig functions in any programming language :p Apr 9, 2021 at 20:08
• @Delfad0r impressive golf! But that equation at the bottom hurts my eyes! Apr 10, 2021 at 21:06
• @flawr It's maths 8) Apr 10, 2021 at 21:09

# JavaScript (ES6), 45 bytes

Expects (a)(b), as Numbers. Returns a Number.

a=>b=>a/b||+(b?1/a?a/b:a*b>0||-1:1/a/b<0&&-0)


Try it online!

## How?

Let $$\\mathbb{R}^*\$$ be $$\\{x\in\mathbb{R}\mid x\neq0\}\$$.

### Direct answers when a/b is truthy

Whenever $$\a/b\$$ is neither NaN nor $$\0\$$, we know for sure that it is the expected answer. The cases that are covered that way are:

• $$\a\in\mathbb{R}^*\$$, $$\b\in\mathbb{R}^*\$$ : standard division of non-zero, non-infinite floats
• $$\a\in\mathbb{R}^*\$$, $$\b=\pm0\$$ : resulting in either $$\+\infty\$$ or $$\-\infty\$$
• $$\a=\pm\infty\$$, $$\b\in\mathbb{R}^*\$$ : resulting in either $$\+\infty\$$ or $$\-\infty\$$
• $$\a=\pm\infty\$$, $$\b=\pm0\$$ : resulting in either $$\+\infty\$$ or $$\-\infty\$$

### Other cases

If $$\a/b\$$ is zero'ish, we test $$\b\$$:

• If $$\b\neq\pm0\$$:
• If $$\1/a\neq\pm0\$$, $$\a/b\$$ is also the correct answer, which is either $$\0\$$ or $$\-0\$$
• If $$\1/a=\pm0\$$ (i.e. $$\a=\pm\infty\$$), we also have $$\b=\pm\infty\$$ and the answer is either $$\1\$$ or $$\-1\$$ depending on the sign of $$\a\times b\$$ (we do a*b>0||-1)
• If $$\b=\pm0\$$, we also have $$\a=\pm0\$$ and the answer is either $$\0\$$ or $$\-0\$$ depending on the signs of $$\a\$$ and $$\b\$$ (we do 1/a/b<0&&-0)

# JavaScript (ES6),  42  33 bytes

Using MarcMush's improvement of Delfad0r's excellent trick with tanh saves  3  12 bytes.

a=>b=>a/b<=1/0?a/b:Math.tanh(a*b)


Try it online!

• Actually MarcMush's improvement is even better, you can save two more bytes by using <=1/0 instead of (not) isNaN: a=>b=>a/b<=1/0?a/b:Math.tanh(a*b) Apr 10, 2021 at 10:03

# Julia 0.7, 26 bytes

imaginary brownie points for using tanh instead of sign (thanks Delfad0r)

a\$b=a/b<=Inf?a/b:tanh(a*b)


Try it online!

• Wow that saves so many bytes, glad to have helped! Apr 10, 2021 at 6:46

# R, 989589 88 bytes

-6 bytes thanks to Giuseppe

function(x,y=abs(scan(t=x)))cat("-"[!!sd(grepl("-",x))],c(z<-y/y,!!y)[1+is.na(z)])


Try it online!

Expects a vector of strings, as R cannot handle signed 0. Infinity will be input and output as Inf.

• x contains the input as 2 strings, and y is the conversion to numeric in absolute value.
• First, call grepl("-",x), giving a vector of two booleans. We need to output a - sign iff the two booleans are different, ie if the standard deviation is non-0.
• Second, compute the division of the two values. R's division agrees with Ash's in most cases, but will give NaN for the two cases which are ambiguous: 0/0 and Inf/Inf. If the quotient is not NaN, we output it; otherwise, we compute the boolean !!y, convert to integer, and output that.

Note that we can use is.na instead of is.nan, as is.na(NaN) returns TRUE. (The two functions are nonetheless not equivalent; is.nan(NA) returns FALSE.)

• 89 bytes. I had this for 95 before your latest golf. Apr 9, 2021 at 19:41
• @Giuseppe Thanks! I was working on something similar but less efficient than your golf. (90 bytes) Apr 9, 2021 at 19:50
• Gotta say, NaN^0==1 is quite surprising to me. 0^0==1 makes sense at least by convention... Apr 9, 2021 at 20:55
• @Giuseppe Well, since ∀ x, x^0=1, it makes sense that the same would apply to NaN. Apr 9, 2021 at 21:33
• I like the scan(t=) trick for converting text to numeric, and have accordingly stolen it. Thanks! Apr 9, 2021 at 22:31

# Scratch, 310 bytes

Try it online!

In scratchblocks4:

when gf clicked
set[Q v]to((N)/(D
if<(Q)=[NaN]>then
if<(A)contains(0)?>then
set[Q v]to(0
else
set[Q v]to(1
end
end
if<<(join(N)(D))contains(-)?>and<not<<(N)contains(-)?>and<(D)contains(-)?>>>>then
if<(Q)contains(-)?>then
else
set[Q v]to(join(-)(Q


Alternatively, 37 blocks. No picture this time!

# JavaScript (Node.js), 32 bytes

a=>b=>a/b+b/a?a/b:Math.sign(a*b)


Try it online!

Rule JavaScript (IEEE 754)
Zero divided by anything is 0 0/0 is NaN;
Same results for other values
Anything other than 0 divided by 0 is Infinity Same Results
Anything other than Infinity divided by Infinity is 0 Same Results
Infinity divided by anything other than Infinity is Infinity Same Results
Infinity divided by Infinity is 1 Infinity/Infinity=NaN
All other division works as normal Same Results

From above comparsion, we can see that, we only need to handle values when a/b is NaN. And whenever a/b is NaN, Math.sign(a*b) is what we want here.

So we use a/b+b/a to test NaN here. As long as a/b is not NaN, a/b, b/a have same signs. And adding them would always yield non-zero value. We know only 0, -0, NaN is falsy. And the value here is non-zero. So we can ensure the result is NaN if a/b+b/a is falsy.

• Nice choice of language... Apr 10, 2021 at 9:43
• @Wasif That actually how IEEE754 works, not specified to some languages.
– tsh
Apr 10, 2021 at 9:58

# C (gcc), 169 157 bytes

Thanks to @ceilingcat for the -12.

tanh seems like the way to go if you want to win this one, so I decided to try this without using any intrinsics, looking at the sign and exponents instead. NaN and denormals are not handled.

Annotated version:

*i,*j,w,x,t,u,v; char*z;
float f(a,b) float a,b; {
i=&a; j=&b; // Get the integer representations of the floats
w=*i*2; x=*j*2; // Move the exponents into the MSB of a copy
t=*j; // Save the original value that will be clobbered
u=3[z=&w]; v=3[z=&x]; // Get the exponents
b=v?
~v? // x/!0
~u?
j=0,a/b: // !INF/!(0,INF)=a/b (indicate normal division)
1/0.: // INF/!(0,INF)=INF
!~u: // INF/INF=1 or !INF/INF=0
u? // x/0
1/0.: // !0/0=INF
0; // 0/0=0

// Adjust the sign if normal division not used
// (if one value is negative, it will flip the sign)
j?*j^=(*i^t)&1<<31:0;
a=b; // Store the result in the return
}

*i,*j,w,x,t,u,v;char*z;float f(a,b)float a,b;{i=&a;j=&b;w=*i*2;x=*j*2;t=*j;u=3[z=&w];v=3[z=&x];b=v?~v?~u?j=0,a/b:1/0.:!~u:u?1/0.:0;j?*j^=(*i^t)&1<<31:0;a=b;}


Try it online!

# Jelly, 48 bytes

ẸṂ=?
ñç÷?
÷×¹?
”-eÇ
Ḋ⁸Ç?
ɠÇŒV
-1*®
7£2ŀ7£×¢


Takes input as newline-separated strings in STDIN, zero is 0.0, and infinity is inf.

Try it online!

### How?

ẸṂ=?           - 1: λxλy: any(x, y) if x == y else min(x, y)
ñç÷?           - 2: λxλy: line3(x, y) if x÷y else line1(x, y)
÷×¹?           - 3: λxλy: x÷y if x else x×y