Why does “np.inf // 2” result in NaN and not infinity? - python

I’m slightly disappointed that np.inf // 2 evaluates to np.nan and not to np.inf, as is the case for normal division.
Is there a reason I’m missing why nan is a better choice than inf?

I'm going to be the person who just points at the C level implementation without any attempt to explain intent or justification:
*mod = fmod(vx, wx);
div = (vx - *mod) / wx;
It looks like in order to calculate divmod for floats (which is called when you just do floor division) it first calculates the modulus and float('inf') %2 only makes sense to be NaN, so when it calculates vx - mod it ends up with NaN so everything propagates nan the rest of the way.
So in short, since the implementation of floor division uses modulus in the calculation and that is NaN, the result for floor division also ends up NaN

Floor division is defined in relation to modulo, both forming one part of the divmod operation.
Binary arithmetic operations
The floor division and modulo operators are connected by the following
identity: x == (x//y)*y + (x%y). Floor division and modulo are also
connected with the built-in function divmod(): divmod(x, y) == (x//y, x%y).
This equivalence cannot hold for x = inf — the remainder inf % y is undefined — making inf // y ambiguous. This means nan is at least as good a result as inf. For simplicity, CPython actually only implements divmod and derives both // and % by dropping a part of the result — this means // inherits nan from divmod.

Infinity is not a number. For example, you can't even say that infinity - infinity is zero. So you're going to run into limitations like this because NumPy is a numerical math package. I suggest using a symbolic math package like SymPy which can handle many different expressions using infinity:
import sympy as sp
sp.floor(sp.oo/2)
sp.oo - 1
sp.oo + sp.oo

Related

Why is log(inf + inf j) equal to (inf + 0.785398 j), In C++/Python/NumPy?

I've been finding a strange behaviour of log functions in C++ and numpy about the behaviour of log function handling complex infinite numbers. Specifically, log(inf + inf * 1j) equals (inf + 0.785398j) when I expect it to be (inf + nan * 1j).
When taking the log of a complex number, the real part is the log of the absolute value of the input and the imaginary part is the phase of the input. Returning 0.785398 as the imaginary part of log(inf + inf * 1j) means it assumes the infs in the real and the imaginary part have the same length.
This assumption does not seem to be consistent with other calculation, for example, inf - inf == nan, inf / inf == nan which assumes 2 infs do not necessarily have the same values.
Why is the assumption for log(inf + inf * 1j) different?
Reproducing C++ code:
#include <complex>
#include <limits>
#include <iostream>
int main() {
double inf = std::numeric_limits<double>::infinity();
std::complex<double> b(inf, inf);
std::complex<double> c = std::log(b);
std::cout << c << "\n";
}
Reproducing Python code (numpy):
import numpy as np
a = complex(float('inf'), float('inf'))
print(np.log(a))
EDIT: Thank you for everyone who's involved in the discussion about the historical reason and the mathematical reason. All of you turn this naive question into a really interesting discussion. The provided answers are all of high quality and I wish I can accept more than 1 answers. However, I've decided to accept #simon's answer as it explains in more detail the mathematical reason and provided a link to the document explaining the logic (although I can't fully understand it).
The free final draft of the C99 specification says on page 491
clog(+∞, +i∞) returns +∞ + iπ/4.
This is still the case currently. The C++ specification explains the same rules with the note
The semantics of this function are intended to be consistent with the C function clog.
I agree the behaviour is confusing from a math point of view, and arguably inconsistent with other inf semantics, as you pointed out. But pragmatically, it's part of the C standard, which makes it part of the C++ standard, and since NumPy normally relies on C behaviour (even in confusing cases), this is inherited in the Python example.
The standard-library cmath.log() function has the same behaviour (if you test it right...):
>>> import cmath
>>> cmath.log(complex(float('inf'), float('inf')))
(inf+0.7853981633974483j)
I have no means to investigate the rationale that went into the C standard. I assume there were pragmatic choices being made here, potentially when considering how these complex functions interact with each other.
The value of 0.785398 (actually pi/4) is consistent with at least some other functions: as you said, the imaginary part of the logarithm of a complex number is identical with the phase angle of the number. This can be reformulated to a question of its own: what is the phase angle of inf + j * inf?
We can calculate the phase angle of a complex number z by atan2(Im(z), Re(z)). With the given number, this boils down to calculating atan2(inf, inf), which is also 0.785398 (or pi/4), both for Numpy and C/C++. So now a similar question could be asked: why is atan2(inf, inf) == 0.785398?
I do not have an answer to the latter (except for "the C/C++ specifications say so", as others already answered), I only have a guess: as atan2(y, x) == atan(y / x) for x > 0, probably someone made the decision in this context to not interpret inf / inf as "undefined" but instead as "a very large number divided by the same very large number". The result of this ratio would be 1, and atan(1) == pi/4 by the mathematical definition of atan.
Probably this is not a satisfying answer, but at least I could hopefully show that the log definition in the given edge case is not completely inconsistent with similar edge cases of related function definitions.
Edit: As I said, consistent with some other functions: it is also consistent with np.angle(complex(np.inf, np.inf)) == 0.785398, for example.
Edit 2: Looking at the source code of an actual atan2 implementation brought up the following code comment:
note that the non obvious cases are y and x both infinite or both zero. for more information, see Branch Cuts for Complex Elementary Functions, or Much Ado About Nothing's Sign Bit, by W. Kahan
I dug up the referenced document, you can find a copy here. In Chapter 8 of this reference, called "Complex zeros and infinities", William Kahan (who is both mathematician and computer scientist and, according to Wikipedia, the "Father of Floating Point") covers the zero and infinity edge cases of complex numbers and arrives at pi/4 for feeding inf + j * inf into the arg function (arg being the function that calculates the phase angle of a complex number, just like np.angle above). You will find this result on page 17 in the linked PDF. I am not mathematician enough for being able to summarize Kahan's rationale (which is to say: I don't really understand it), but maybe someone else can.
If we consider this from a pure maths point of view then we can look at operations in terms of limits e.g. as x goes to infinity, 1/x tends to 0 (denoted lim(x => inf) 1/x = 0), which is what we observe with floating points.
For operations on 2 infinities, we consider each infinity separately. Thus:
lim(x => inf) x/1 = inf
lim(x => inf) 1/x = 0
and in general we say inf/x = inf, and x/inf = 0. Thus:
lim(x => inf) inf/x = inf
lim(x => inf) x/inf = 0
Which of these 2 should we prefer? The spec for floats sidesteps by declaring it a NaN.
For complex logs however we observe:
lim(x=>inf) log(x + 0j) = inf + 0j
lim(x=>inf) log(0 + xj) = inf + pi/2j
lim(x=>inf) log(inf + xj) = inf + 0j
lim(x=>inf) log(x + infj) = inf + pi/2j
There is still a contradiction, but rather than being between 0 and inf, it is between 0 and pi/2, so the spec authors chose to split the difference. Why they made this chooice I couldn't say, but floating point infinities are not mathematical infinities, but instead represent 'this number is too large for representation'. Given that uses of log(complex) are likely to be more pure mathematical than those for subtraction and division, the authors may have felt that retaining the identity im(log(x+xj)) == pi/4 was useful.

Why is the value of 1**Inf equal to 1, not NaN?

Why is 1**Inf == 1 ?
I believe it should be NaN, just like Inf-Inf or Inf/Inf.
How is exponentiation implemented on floats in python?
exp(y*log(x)) would get correct result :/
You are right, mathematically, the value of 1∞ is indeterminate.
However, Python doesn't follow the maths exactly in this case. The document of math.pow says:
math.pow(x, y)
Return x raised to the power y. Exceptional cases follow Annex ‘F’ of the C99 standard as far as possible. In particular, pow(1.0, x) and pow(x, 0.0) always return 1.0, even when x is a zero or a NaN.
Floating-point arithmetic is not real-number arithmetic. Notions of "correct" informed by real analysis do not necessarily apply to floating-point.
In this case, however, the trouble is just that pow fundamentally represents two similar but distinct functions:
Exponentiation with an integer power, which is naturally a function RxZ --> R (or RxN --> R).
The two-variable complex function given by pow(x,y) = exp(y * log(x)) restricted to the real line.
These functions agree for normal values, but differ in their edge cases at zero, infinity, and along the negative real axis (which is traditionally the branch cut for the second function).
These two functions are sometimes divided up to make the edge cases more reasonable; when that's done the first function is called pown and the second is called powr; as you have noticed pow is a conflation of the two functions, and uses the edge cases for these values that come from pown.
Technically 1^inf is defined as limit(1^x, x->inf). 1^x = 1 for any x >1, so it should be limit(1,x->inf) = 1, not NaN

Why is -1/2 evaluated to 0 in C++, but -1 in Python?

C++: cout << -1/2 evaluates to 0
Python: -1/2 evaluates to -1.
Why is this the case?
Integer division in C++ rounds toward 0, and in Python, it rounds toward -infinity.
People dealing with these things in the abstract tend to feel that rounding toward negative infinity makes more sense (that means it's compatible with the modulo function as defined in mathematics, rather than % having a somewhat funny meaning). The tradition in programming languages is to round toward 0--this wasn't originally defined in C++ (following C's example at the time), but eventually C++ (and C) defined it this way, copying Fortran.
From the Python docs (emphasis mine):
The / (division) and // (floor division) operators yield the quotient of their arguments. The numeric arguments are first converted to a common type. Plain or long integer division yields an integer of the same type; the result is that of mathematical division with the ‘floor’ function applied to the result.
The floor function rounds to the number closest to negative infinity, hence -1.
For C++, from this reference: 5.2 — Arithmetic operators
It is easiest to think of the division operator as having two
different “modes”. If both of the operands are integers, the division
operator performs integer division. Integer division drops any
fractions and returns an integer value.
Thus, -1/2 would yield -0.5 with the fraction dropped, yielding 0.
As SethMMorton indicated, Python's rule is floor, which yields -1. It's described in 5. Expressions.
Put in the terms that Mike Graham mentioned, floor is a round toward minus infinity. Dropping the fraction is a round toward zero.
I am not sure about Python, but in C++ integer/integer = integer, and therefore in case of -1/2 is -0.5 which is rounded automatically to integer and therefore you get the 0 answer.
In case of Python, maybe the system used the floor function to convert the result into an integer.

Python gmpy2 f_divmod function confusion

I'm pretty new to python and i just started playing with gmpy2, but i'm a little confused about one of the functions and gmpy's documentation isn't helpful in this regard:
I'd like to do division with a modulus (as well as a floor) so i found the f_divmod() function:
f_divmod(...) f_divmod(x, y) returns the quotient and remainder of x
divided by y. The quotient is rounded towards -Inf (floor rounding)
and the remainder will have the same sign as y. x and y must be
integers.
However if this does what i think it should do (and that is probably my mistake), it should do: x / y % m, and i see no way to provide an m. Is this the wrong function for that, or do i need to somehow define a modulus elsewhere?
I see my alternative being:
c = gmpy2.f_div(a, b) % m
Thanks in advance!
Note: I maintain gmpy2.
gmpy2.f_divmod() (along with gmpy2.c_divmod(), gmpy2.t_divmod(), and gmpy2.divmod()) are patterned after the builtin divmod(). All the functions return the quotient and remainder but each functions uses a slightly different rule to compute the quotient and remainder. The names are meant to imply that the functions return the tuple (a // b, a % b). They don't do division followed by mod.
If you want to calculate the quotient using floor division, and then reduce that result modulo another number, then your alternative is correct.
Slightly off-topic hint: You should get into the habit of using // for integer division. In Python 3, / becomes floating point division. // is integer division in both Python 2 and 3.

How to implement division with round-towards-infinity in Python

I want 3/2 to equal 2 not 1.5
I know there's a mathematical term for that operation(not called rounding up), but I can't recall it right now.
Anyway, how do i do that without having to do two functions?
ex of what I do NOT want:
answer = 3/2 then math.ceil(answer)=2 (why does math.ceil(3/2)=1?)
ex of what I DO want:
"function"(3/2) = 2
To give a short answer...
Python only offers native operators for two types of division: "true" division, and "round down" division. So what you want isn't available as a single function. However, it is possible to easily implement a number of different types of division-with-rounding using some short expressions.
Per the title's request: given strictly integer inputs, "round up" division can be implemented using (a+(-a%b))//b, and "round away from zero" division can be implemented using the more complex a//b if a*b<0 else (a+(-a%b))//b. One of those is probably what you want. As to why...
To give a longer answer...
First, let me answer the subquestion about why 3/2==1 and math.ceil(3/2)==1.0, by way of explaining how the Python division operator works. There are two main issues at play...
float vs int division: Under Python 2, division behaves differently depending on the type of the inputs. If both a and b are integers, a/b performs "round down" or "floor integer" division (eg 3/2==1, but -3/2==-2). This is equivalent to int(math.floor(float(a)/b)) .
But if at least one of a and b are floats, Python performs "true" division, and gives you a float result (eg 3.0/2==1.5, and -3.0/2==-1.5). This is why you'll sometimes see the construction float(a)/b: it's being used to force true division even both inputs are integers (eg float(3)/2==1.5). This is why your example math.ceil(3/2) returns 1.0, whereas math.ceil(float(3)/2) returns 2.0. The result has already been rounded down before it even reaches math.ceil().
"true division" by default: In 2001, it was decided (PEP 238) that Python's division operator should be changed so that it always performs "true" division, regardless of whether the inputs are floats or integers (eg, this would make 3/2==1.5). In order to not break existing scripts, the change in default behavior was deferred until Python 3.0; in order to get this behavior under Python 2.x, you have to enable it per-file by adding from __future__ import division to the top of the file. Otherwise the old type-dependant behavior is used.
But "round down" division is still frequently needed, so the PEP didn't do way with it entirely. Instead, it introduced a new division operator: a//b, which always performs round down division, even if the inputs include floats. This can be used without doing anything special under both Python 2.2+ and 3.x.
That out of that way, division-with-rounding:
In order to simplify things, the following expressions all use the a//b operator when working on integers, since it will behave the same under all python versions. As well, I'm making an assumption that 0<=a%b<b if b is positive, and b<=a%b<=0 if b is negative. This is how Python behaves, but other languages may have slightly different modulus operators.
The four basic types of integer division with rounding:
"round down" aka "floor integer" aka "round to minus infinity" divsion: python offers this natively via a//b.
"round up" aka "ceiling integer" aka "round to positive infinity" division: this can be achieved via int(math.ceil(float(a)/b)) or (a+(-a%b))//b. The latter equation works because -a%b is 0 if a is a multiple of b, and is otherwise the amount we need to add to a to get to the next highest multiple.
"round towards zero" aka "truncated" division - this can be achieved via int(float(a)/b). Doing this without using floating point is trickier... since Python only offers round-down integer division, and the % operator has a similar round-down bias, we don't have any non-floating-point operators which round symmetrically about 0. So the only way I can think of is to construct a piecewise expression out of round-down and round-up: a//b if a*b>0 else (a+(-a%b))//b.
"round away from zero" aka "round to (either) infinity" division - unfortunately, this is even trickier than round-towards-zero. We can't leverage the truncating behavior of the int operator anymore, so I can't think of a simple expression even when including floating-point ops. So I have to go with the inverse of the round-to-zero expression, and use a//b if a*b<0 else (a+(-a%b))//b.
Note that if you're only using positive integers, (a+b-1)//b provides round up / away from zero even more efficiently than any of the above solutions, but falls apart for negatives.
Hope that helps... and happy to make edits if anyone can suggest better equations for round to/away from zero. I find the ones I have particularly unsatisfactory.
Integral division in Python 3:
3 // 2 == 1
Non-integral division in Python 3:
3 / 2 == 1.5
What you're talking about is not a division by all means.
The intent of the OP's question is "How to implement division with round-towards-infinity in Python" (suggest you change the title).
This is a perfectly legitimate rounding mode as per the IEEE-754 standard (read this overview), and the term for it is "round towards infinity" (or "round away from zero"). Most of the 9 downvotes were beating up on the OP unfairly. Yes, there is no single-function way to do this in native Python, but we can use round(float(a)/b) or else subclass numbers.Number and override __div__().
The OP would need to clarify whether they want -3/2 to round to -2 or -1 (or don't-care for negative operands). Since they already said they don't want round-upwards, we can infer -3/2 should round to -2.
Enough theory. For implementations:
If you just want the fast-and-dirty one-line solution for round-towards-infinity , use round(float(a)/b)
math.ceil(float(a)/b) gives you round-upwards, which you said you don't want
But if this is your default division operation, or you are doing a lot of this, then do like the pseudocode below: inherit from one of the subclasses of numbers.Number Real, Rational or Integral (new in 2.6), redefine __div__() or else define a non-default alternative __divra__() operation. You could define a class member or classmethod rounding_mode and look it up during divisions. Be careful of __rdiv__() and mixing with ordinary floats though.
.
import numbers
class NumberWithRounding(numbers.Integral):
# Here you could implement a classmethod setRoundingMode() or member rounding_mode
def __div__(self,other):
# here you could consider value of rounding_mode, or else hardwire it like:
return round(float(self)/other)
# You also have to raise ImplementationError/ pass/ or implement the other 31
# methods for Float: __abs__(),...,__xor__() Just shortcut that for now...
When you divide two integers, the result is an integer.
3 / 2 equals 1, not 1.5.
See the documentation, note 1:
For (plain or long) integer division, the result is an integer. The result is always rounded towards minus infinity: 1/2 is 0, (-1)/2 is -1, 1/(-2) is -1, and (-1)/(-2) is 0. Note that the result is a long integer if either operand is a long integer, regardless of the numeric value.
Once you get 1 from the division, there is no way to turn that into 2.
To get 1.5, you need floating-point division: 3.0 / 2.
You can then call math.ceil to get 2.
You are mistaken; there is no mathematical function that divides, then rounds up.
The best you can do is write your own function that takes two floats and calls math.ceil.
What you probably want is something like:
math.ceil(3.0/2.0)
# or
math.ceil(float(3)/float(2))
You could also do an import from future:
from __future__ import division
math.ceil(3/2) # == 2
But, if you do this, to get the current behavior of integer division you need to use the double slash:
3 // 2 == 1 # True
Integer division with ceiling rounding (to +Inf), floor rounding (to -Inf), and truncation (to 0) is available in gmpy2.
>>> gmpy2.c_div(3,2)
mpz(2)
>>> help(gmpy2.c_div)
Help on built-in function c_div in module gmpy2:
c_div(...)
c_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards +Inf (ceiling rounding). x and y must be integers.
>>> help(gmpy2.f_div)
Help on built-in function f_div in module gmpy2:
f_div(...)
f_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards -Inf (floor rounding). x and y must be integers.
>>> help(gmpy2.t_div)
Help on built-in function t_div in module gmpy2:
t_div(...)
t_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards 0. x and y must be integers.
>>>
gmpy2 is available at http://code.google.com/p/gmpy/
(Disclaimer: I'm the current maintainer of gmpy and gmpy2.)
I think that what you're looking for is this:
assuming you have x (3) and y (2),
result = (x + y - 1) // y;
this is the equivalent of a ceiling without the use of floating points.
Of course, y cannot be 0.
Firstly, you want to be using floating-point division in the arguments. Use:
from __future__ import division
If you always want to round up, so f(3/2)==2 and f(1.4)==2, then you want f to be math.trunc(math.ceil(x)).
If you want to get the closest integer, but have ties round up, then you want math.trunc(x + 0.5). That way f(3/2)==2 and f(1.4)==1.

Categories