6

I want to calculate the Determinant of a Singular Matrix (which has a 0 determinant) with Numpy and when I print the determinant it shows a really small number (which is nearly zero = -7.09974814699e-30) but not zero itself...

when I try to print the determinant either with %s, %d, or %f, sometimes it's zero, sometimes -0 and sometimes -7.09974814699e-30 .

Here's the code:

import numpy as np

array = np.arange(16)
array = array.reshape(4, -1)
determinant = np.linalg.det(array)

print("Determinant is %s" % determinant)
print("Determinant is %d" % determinant)
print("Determinant is %f" % determinant)

Determinant is -7.09974814699e-30
Determinant is 0
Determinant is -0.000000

How can I make Numpy treat really small numbers such as -7.09974814699e-30 as zero and show zero to me. I also asked this question before, if you take a look at the matrix you see that it's filled with really small numbers but not zero while it should be a diagonal matrix with numbers on the diagonal and zeros elsewhere.

jared
  • 4,165
  • 1
  • 8
  • 31
Cypher
  • 2,374
  • 4
  • 24
  • 36
  • you can put a threshold: if determinant < 0.00001 then determinant = 0.0 – Nikaido Apr 04 '16 at 06:06
  • I was hoping if there was a global way to make Numpy show really small values as zero and avoid crowding the code with many if-else checks... – Cypher Apr 04 '16 at 06:09
  • you may want to consider using [numpy.isclose](http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.isclose.html) that checks values are within tolerance given by argument. – Kenji Noguchi Apr 04 '16 at 07:07

4 Answers4

4
>>> if np.abs(determinant) < 0.000001:
...     determinant=0
...
>>> print determinant
0

In case of array you can do it using a single operation (see my answer to your other question: https://stackoverflow.com/a/36395905/5088142)

To set array elements that are less than eps to zero:

array[np.abs(array) < eps] = 0
rafaelc
  • 57,686
  • 15
  • 58
  • 82
Yaron
  • 10,166
  • 9
  • 45
  • 65
3

You can truncate less significant digits with np.round . But it's better do keep accuracy for float arithmetic. What you have to control is just the format of the final output, with the str.format function.

In [7]: a=rand(12,12)
In [8]: deta=det(a)
#0.0063854296972496311

In [10]: detar=det(a.round(3))
# 0.0063817871557592153

In [12]: '{:.5f}'.format(deta)
Out[12]: '0.00639'

In [13]: '{:.5f}'.format(detar)
Out[13]: '0.00638'

Last line shows a false result due to earlier optimization.

jared
  • 4,165
  • 1
  • 8
  • 31
B. M.
  • 18,243
  • 2
  • 35
  • 54
2

Use numpy.set_printoptions and enable the suppress option:

>>> import numpy as np
>>> np.set_printoptions(precision=3, suppress=True)
>>> array = np.arange(16)
>>> array = array.reshape(4, -1)
>>> determinant = np.linalg.det(array)
>>> print("Determinant is:", determinant)
Determinant is: 0.0
xFullArgon
  • 85
  • 1
  • 1
  • 8
  • this works, but it also modifies the way that larger numbers are printed, and supresses the use of scientific notation for large numbers (> 1e3) - [the documentation](https://numpy.org/doc/stable/reference/generated/numpy.set_printoptions.html) for this provides some further info – Taylor Alex Raine Apr 16 '22 at 00:21
1

I am using Python 2.7.11 |Anaconda custom (x86_64)| (default, Dec 6 2015, 18:57:58) IPython 4.0.3 -- An enhanced Interactive Python. and I got results as below,

In [6]: print("Determinant is %s" % determinant)
Determinant is 0.0

In [7]: print("Determinant is %d" % determinant)
Determinant is 0

In [8]: print("Determinant is %f" % determinant)
Determinant is 0.000000

I think if you update numpy it might fit it for you else you use below approach

In [9]: sam = 0.000000121

In [10]: sam
Out[10]: 1.21e-07

In [11]: print sam if sam > 0.00001 else 1
1

This does not exactly answer your question "How can I make Numpy treat really small numbers such as -7.09974814699e-30 as zero and show zero to me.", I think you do work around for this.

In general as it comes to floats/exponents, calculations beyond certain point carry minor error,.. for example by your e power -30 case. So if you are using high level floats or exponents it better you expect some error.

sam
  • 1,819
  • 1
  • 18
  • 30