This is a bit tricky. You can't always get logarithmically spaced numbers. As in your example, first part is rather linear. If you are OK with that, I have a solution. But for the solution, you should understand why you have duplicates.

Logarithmic scale satisfies the condition:

s[n+1]/s[n] = constant

Let's call this constant r for ratio. For n of these numbers between range 1...size, you'll get:

1, r, r**2, r**3, ..., r**(n-1)=size

So this gives you:

r = size ** (1/(n-1))

In your case, n=100 and size=10000, r will be ~1.0974987654930561, which means, if you start with 1, your next number will be 1.0974987654930561 which is then rounded to 1 again. Thus your duplicates. This issue is present for small numbers. After a sufficiently large number, multiplying with ratio will result in a different rounded integer.

Keeping this in mind, your best bet is to add consecutive integers up to a certain point so that this multiplication with the ratio is no longer an issue. Then you can continue with the logarithmic scaling. The following function does that:

import numpy as np

def gen_log_space(limit, n):
    result = [1]
    if n>1:  # just a check to avoid ZeroDivisionError
        ratio = (float(limit)/result[-1]) ** (1.0/(n-len(result)))
    while len(result)<n:
        next_value = result[-1]*ratio
        if next_value - result[-1] >= 1:
            # safe zone. next_value will be a different integer
            result.append(next_value)
        else:
            # problem! same integer. we need to find next_value by artificially incrementing previous value
            result.append(result[-1]+1)
            # recalculate the ratio so that the remaining values will scale correctly
            ratio = (float(limit)/result[-1]) ** (1.0/(n-len(result)))
    # round, re-adjust to 0 indexing (i.e. minus 1) and return np.uint64 array
    return np.array(list(map(lambda x: round(x)-1, result)), dtype=np.uint64)

Python 3 update: Last line used to be return np.array(map(lambda x: round(x)-1, result), dtype=np.uint64) in Python 2

Here are some examples using it:

In [157]: x = gen_log_space(10000, 100)

In [158]: x.size
Out[158]: 100

In [159]: len(set(x))
Out[159]: 100

In [160]: y = gen_log_space(2000, 50)

In [161]: y.size
Out[161]: 50

In [162]: len(set(y))
Out[162]: 50

In [163]: y
Out[163]:
array([   0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   11,
         13,   14,   17,   19,   22,   25,   29,   33,   38,   43,   49,
         56,   65,   74,   84,   96,  110,  125,  143,  164,  187,  213,
        243,  277,  316,  361,  412,  470,  536,  612,  698,  796,  908,
       1035, 1181, 1347, 1537, 1753, 1999], dtype=uint64)

And just to show you how logarithmic the results are, here is a semilog plot of the output for x = gen_log_scale(10000, 100) (as you can see, left part is not really logarithmic):

Answer from Avaris on Stack Overflow
🌐
NumPy
numpy.org › doc › stable › reference › generated › numpy.logspace.html
numpy.logspace — NumPy v2.4 Manual
>>> import numpy as np >>> np.logspace(2.0, 3.0, num=4) array([ 100. , 215.443469 , 464.15888336, 1000. ]) >>> np.logspace(2.0, 3.0, num=4, endpoint=False) array([100. , 177.827941 , 316.22776602, 562.34132519]) >>> np.logspace(2.0, 3.0, num=4, base=2.0) array([4.
🌐
NumPy
numpy.org › devdocs › reference › generated › numpy.logspace.html
numpy.logspace — NumPy v2.5.dev0 Manual
The inferred type will never be an integer; float is chosen even if the arguments would produce an array of integers. ... The axis in the result to store the samples. Relevant only if start, stop, or base are array-like. By default (0), the samples will be along a new axis inserted at the beginning.
Top answer
1 of 4
19

This is a bit tricky. You can't always get logarithmically spaced numbers. As in your example, first part is rather linear. If you are OK with that, I have a solution. But for the solution, you should understand why you have duplicates.

Logarithmic scale satisfies the condition:

s[n+1]/s[n] = constant

Let's call this constant r for ratio. For n of these numbers between range 1...size, you'll get:

1, r, r**2, r**3, ..., r**(n-1)=size

So this gives you:

r = size ** (1/(n-1))

In your case, n=100 and size=10000, r will be ~1.0974987654930561, which means, if you start with 1, your next number will be 1.0974987654930561 which is then rounded to 1 again. Thus your duplicates. This issue is present for small numbers. After a sufficiently large number, multiplying with ratio will result in a different rounded integer.

Keeping this in mind, your best bet is to add consecutive integers up to a certain point so that this multiplication with the ratio is no longer an issue. Then you can continue with the logarithmic scaling. The following function does that:

import numpy as np

def gen_log_space(limit, n):
    result = [1]
    if n>1:  # just a check to avoid ZeroDivisionError
        ratio = (float(limit)/result[-1]) ** (1.0/(n-len(result)))
    while len(result)<n:
        next_value = result[-1]*ratio
        if next_value - result[-1] >= 1:
            # safe zone. next_value will be a different integer
            result.append(next_value)
        else:
            # problem! same integer. we need to find next_value by artificially incrementing previous value
            result.append(result[-1]+1)
            # recalculate the ratio so that the remaining values will scale correctly
            ratio = (float(limit)/result[-1]) ** (1.0/(n-len(result)))
    # round, re-adjust to 0 indexing (i.e. minus 1) and return np.uint64 array
    return np.array(list(map(lambda x: round(x)-1, result)), dtype=np.uint64)

Python 3 update: Last line used to be return np.array(map(lambda x: round(x)-1, result), dtype=np.uint64) in Python 2

Here are some examples using it:

In [157]: x = gen_log_space(10000, 100)

In [158]: x.size
Out[158]: 100

In [159]: len(set(x))
Out[159]: 100

In [160]: y = gen_log_space(2000, 50)

In [161]: y.size
Out[161]: 50

In [162]: len(set(y))
Out[162]: 50

In [163]: y
Out[163]:
array([   0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   11,
         13,   14,   17,   19,   22,   25,   29,   33,   38,   43,   49,
         56,   65,   74,   84,   96,  110,  125,  143,  164,  187,  213,
        243,  277,  316,  361,  412,  470,  536,  612,  698,  796,  908,
       1035, 1181, 1347, 1537, 1753, 1999], dtype=uint64)

And just to show you how logarithmic the results are, here is a semilog plot of the output for x = gen_log_scale(10000, 100) (as you can see, left part is not really logarithmic):

2 of 4
4

The approach in Avaris's answer of generating your log-spaced points directly, is definitely the way to go. But I thought it would be interesting to see how to pick the appropriate value to pass to logspace to get what you want.

The values in the array generated by logspace(0, k, n) are the numbers 10ik / (n−1) for 0 ≤ i < n:

>>> numpy.logspace(0, 2, 10)
array([   1.        ,    1.66810054,    2.7825594 ,    4.64158883,
          7.74263683,   12.91549665,   21.5443469 ,   35.93813664,
         59.94842503,  100.        ])
>>> [10 ** (i * 2 / 9.0) for i in xrange(10)]
[1.0, 1.6681005372000588, 2.7825594022071245, 4.641588833612778,
 7.742636826811269, 12.91549665014884, 21.544346900318832,
 35.938136638046274, 59.94842503189409, 100.0]

This sequence consists of an initial segment where the values are more closely than unit spaced (and so there may be duplicates when they are rounded to the nearest integer), followed by a segment where the values are more widely than unit spaced and there are no duplicates.

>>> ' '.join('{:.2f}'.format(10 ** (i * 2 / 19.0)) for i in xrange(20))
'1.00 1.27 1.62 2.07 2.64 3.36 4.28 5.46 6.95 8.86 11.29 14.38 18.33 23.36
 29.76 37.93 48.33 61.58 78.48 100.00'
>>> [int(0.5 + 10 ** (i * 2 / 19.0)) for i in xrange(20)]
[1, 1, 2, 2, 3, 3, 4, 5, 7, 9, 11, 14, 18, 23, 30, 38, 48, 62, 78, 100]

The spacing between values is s(i) = 10iK − 10(i−1)K, where K = k / (n − 1). Let m be the smallest value such that s(m) ≥ 1. (m = 7 in the example above.) Then when duplicates are removed, there are exactly ⌊½ + 10(m−1)K⌋ + nm remaining numbers.

A bit of algebra finds:

m = ⌈ − log(1 − 10K) / K log 10 ⌉

Let's check that.

from math import ceil, floor, log

def logspace_size(k, n):
    """
    Return the number of distinct integers we'll get if we round
    `numpy.logspace(0, k, n)` to the nearest integers and remove
    duplicates.

    >>> logspace_size(4, 100)
    84
    >>> logspace_size(4, 121)
    100
    >>> from numpy import around, logspace
    >>> all(logspace_size(k, n) == len(set(around(logspace(0, k, n))))
    ...     for k in xrange(1,10) for n in xrange(2,100))
    True
    """
    K = float(k) / (n - 1)
    m = int(ceil(- log(1 - 10 ** -K) / (K * log(10))))
    if m < n:
        return int(0.5 + 10 ** ((m - 1) * K)) + n - m
    else:
        return int(0.5 + 10 ** ((n - 1) * K))

The doctests pass, so this looks good to me. So all you need to do is find n such that logspace_size(4, n) == 100. You could do this by binary chop or one of the scipy.optimize methods:

>>> f = lambda x, k, n:(logspace_size(k, x) - n)**2
>>> int(round(scipy.optimize.fmin(f, 100, args=(4,100), xtol=0.5, ftol=0.5)[0]))
Optimization terminated successfully.
         Current function value: 0.015625
         Iterations: 8
         Function evaluations: 17
122
🌐
NumPy
numpy.org › doc › 2.1 › reference › generated › numpy.logspace.html
numpy.logspace — NumPy v2.1 Manual
>>> import numpy as np >>> np.logspace(2.0, 3.0, num=4) array([ 100. , 215.443469 , 464.15888336, 1000. ]) >>> np.logspace(2.0, 3.0, num=4, endpoint=False) array([100. , 177.827941 , 316.22776602, 562.34132519]) >>> np.logspace(2.0, 3.0, num=4, base=2.0) array([4.
🌐
NumPy
numpy.org › doc › 2.3 › reference › generated › numpy.logspace.html
numpy.logspace — NumPy v2.3 Manual
>>> import numpy as np >>> np.logspace(2.0, 3.0, num=4) array([ 100. , 215.443469 , 464.15888336, 1000. ]) >>> np.logspace(2.0, 3.0, num=4, endpoint=False) array([100. , 177.827941 , 316.22776602, 562.34132519]) >>> np.logspace(2.0, 3.0, num=4, base=2.0) array([4.
🌐
w3resource
w3resource.com › numpy › array-creation › logspace.php
NumPy: numpy.logspace() function - w3resource
March 21, 2023 - Example: Logarithmically spaced arrays using NumPy's logspace function. >>> import numpy as np >>> np.logspace(4.0, 5.0, num=3) array([ 10000. , 31622.77660168, 100000. ]) >>> np.logspace(4.0, 5.0, num=3, endpoint=False) array([ 10000. , 21544.34690032, 46415.88833613]) >>> np.logspace(4.0, 5.0, num=3, base=2.0) array([ 16.
🌐
GeeksforGeeks
geeksforgeeks.org › python › numpy-logspace-python
numpy.logspace() in Python - GeeksforGeeks
February 14, 2026 - ... The output array can be converted to a specific data type using the dtype parameter. ... Explanation: dtype=int converts float values to integers and decimal values are removed during conversion.
🌐
NumPy
numpy.org › doc › 2.0 › reference › generated › numpy.logspace.html
numpy.logspace — NumPy v2.0 Manual
>>> np.logspace(2.0, 3.0, num=4) array([ 100. , 215.443469 , 464.15888336, 1000. ]) >>> np.logspace(2.0, 3.0, num=4, endpoint=False) array([100. , 177.827941 , 316.22776602, 562.34132519]) >>> np.logspace(2.0, 3.0, num=4, base=2.0) array([4. , 5.0396842 , 6.34960421, 8.
Find elsewhere
🌐
Real Python
realpython.com › np-linspace-numpy
np.linspace(): Create Evenly or Non-Evenly Spaced Arrays – Real Python
December 1, 2023 - The function np.logspace() creates a logarithmic space in which the numbers created are evenly spaced on a log scale.
🌐
Programiz
programiz.com › python-programming › numpy › methods › logspace
NumPy logspace()
The logspace() method creates an array with evenly spaced numbers on a logarithm scale. ... # create an array with 3 elements between 10^5 and 10^10 array1 = np.logspace(5, 10, 3) print(array1) # Output: [1.00000000e+05 3.16227766e+07 1.00000000e+10]
🌐
datagy
datagy.io › home › numpy › numpy logspace: understanding the np.logspace() function
NumPy logspace: Understanding the np.logspace() Function • datagy
December 30, 2022 - In the next section, you’ll learn how to add additional dimensions to the range returned by the np.logspace() function. By default, NumPy will create an array with a single dimension. However, we can also pass in arrays of values into the start and stop values and we can increase the dimensionality of what gets returned. Let’s see how we can pass lists of values as our start and stop parameters: # Changing the Dimensionality of Our Range import numpy as np print(np.logspace(start=[1,10], stop=[10,20], num=5, base=2, dtype='int')) # Returns: # [[ 2 1024] # [ 9 5792] # [ 45 32768] # [ 215 185363] # [ 1024 1048576]]
🌐
Medium
medium.com › @amit25173 › numpy-logspace-with-examples-87aed47b4728
numpy.logspace with Examples. If you think you need to spend $2,000… | by Amit Yadav | Medium
February 9, 2025 - ... If you don’t specify the base parameter, it defaults to 10. That’s why numpy.logspace often generates numbers like 101,102,10310^1, 10^2, 10^3101,102,103. Of course, you can change the base to suit your needs.
🌐
Spark By {Examples}
sparkbyexamples.com › home › python › how to use numpy logspace() in python
How to Use NumPy logspace() in Python - Spark By {Examples}
March 27, 2024 - If you are in a hurry, below are some quick examples of how to use logspace() function in Python NumPy. # Below are the quick examples # Example 1: Equally spaced values on log scale between 2 and 3 arr = np.logspace(2, 3) # Example 2: Six equally spaced values on log scale between 2 and 3 arr = np.logspace(2, 3, num=6) # Example 3: Exclude the stop endpoint arr = np.logspace(2, 3, num=6, endpoint=False) # Example 4: Use a different log base for the log scale arr = np.logspace(2, 3, num=7, base=2) # Example 5: Graphical representation of numpy.logspace() using matplotlib module arr = 40 a1 = np.logspace(0.6, 4, arr, endpoint=True) a2 = np.logspace(0.6, 4, arr, endpoint=False) b = np.zeros(arr) plt.plot(a1, b, 'o') plt.ylim([-0.8, 4]) plt.show() # Example 6: Graphical representation of numpy.logspace() arr = np.logspace(2, 3, num=6) arr1 = np.zeros(6) plt.plot(arr, arr1, 'o')
🌐
TutorialsPoint
tutorialspoint.com › numpy › numpy_logspace_function.htm
Numpy logspace() Function
In the following example, we have generated a numpy array with integer values on the logarithmic scale value by setting the dtype parameter to int − · import numpy as np logspace_int = np.logspace(1, 3, num=4, dtype=int) print("Logarithmic space array with integer data type:\n", logspace_int)
🌐
NumPy
numpy.org › doc › 1.20 › reference › generated › numpy.logspace.html
numpy.logspace — NumPy v1.20 Manual
>>> np.logspace(2.0, 3.0, num=4) array([ 100. , 215.443469 , 464.15888336, 1000. ]) >>> np.logspace(2.0, 3.0, num=4, endpoint=False) array([100. , 177.827941 , 316.22776602, 562.34132519]) >>> np.logspace(2.0, 3.0, num=4, base=2.0) array([4. , 5.0396842 , 6.34960421, 8.
🌐
Data Science Parichay
datascienceparichay.com › home › blog › numpy logspace() – usage and examples
Numpy logspace() - Usage and Examples - Data Science Parichay
June 17, 2022 - Note that, the inferred type will never be an integer, float is chosen even if the arguments would produce an array of integers. You can, however, specify the dtype if you don’t want it to be inferred.
🌐
Spark Code Hub
sparkcodehub.com › numpy › basics › logspace-guide
Mastering NumPy logspace(): Creating Logarithmic Sequences with Precision
np.logspace() is a specialized and powerful method for generating arrays of numbers spaced evenly on a logarithmic scale.
🌐
Tutorial Gateway
tutorialgateway.org › python-numpy-logspace
Python NumPy logspace
December 20, 2024 - In the third line, we used endpoint = False so that the stop value would be less than 5. In the fourth line, the dtype = int will convert the result to integers. import numpy as np a = np.logspace(1, 3, num = 5) print(a) b = np.logspace(1.0, 5.0, num = 5, base = 2) print(b) c = np.logspace(1.0, 5.0, num = 5, endpoint = False, base = 2) print(c) d = np.logspace(1.0, 5.0, num = 5, base = 2, dtype = int) print(d) [ 10.
🌐
Vultr Docs
docs.vultr.com › python › third-party › numpy › logspace
Python Numpy logspace() - Generate Logarithmic Spaced Array | Vultr Docs
November 14, 2024 - In this article, you will learn how to generate logarithmically spaced arrays using the numpy.logspace() function.