How to represent an unbounded variable as number between 0 and 1 I want to represent a variable as a number between 0 and 1. The variable is a non-negative integer with no inherent bound. I map 0 to 0 but what can I map to 1 or numbers between 0 and 1?
I could use the history of that variable to provide the limits. This would mean I have to restate old statistics if the maximum increases. Do I have to do this or are there other tricks I should know about?
 A: A very common trick to do so (e.g., in connectionist modeling) is to use the hyperbolic tangent tanh as the 'squashing function".
It automatically fits all numbers into the interval between -1 and 1. Which in your case restricts the range from 0 to 1.
In r and matlab you get it via tanh(). 
Another squashing function is the logistic function (thanks to Simon for the name), provided by $ f(x) = 1 / (1 + e ^{-x} ) $, which restricts the range from 0 to 1 (with 0 mapped to .5). So you would have to multiply the result by 2 and subtract 1 to fit your data into the interval between 0 and 1.
Here is some simple R code which plots both functions (tanh in red, logistic in blue) so you can see how both squash:
x <- seq(0,20,0.001)
plot(x,tanh(x),pch=".", col="red", ylab="y")
points(x,(1 / (1 + exp(-x)))*2-1, pch=".",col="blue")

A: In addition to the good suggestions by Henrik and Simon Byrne, you could use f(x) = x/(x+1).  By way of comparison, the logistic function will exaggerate differences as x grows larger.  That is, the difference between f(x) and f(x+1) will be larger with the logistic function than with f(x) = x/(x+1).  You may or may not want that effect.
A: As often, my first question was going to be "why do you want to do this", then I saw you've already answered this in the comments to the question: "I am measuring content across many different dimensions and I want to be able to make comparisons in terms of how relevant a given piece of content is. Additionally, I want to display values across these dimensions that is explicable and easily understood."
There is no reason to normalize the data so that the max is 1 and the min is zero in order to achieve this, and my opinion is that this would be a bad idea in general. The max or min values could very easily be outliers that are unrepresentative of the population distribution. @osknows parting remark about using $z$-scores is a much better idea. $z$-scores (aka standard scores) normalize each variable using its standard deviation rather than its range. The standard deviation is less influenced by outliers. In order to use $z$-scores, it's preferable that each variable has a roughly normal distribution, or at least has a roughly symmetric distribution (i.e. isn't severely skew) but if necessary you can apply some appropriate data transformation first in order to achieve this; which transformation to use could be determined by finding the best fitting Box–Cox transformation.
A: Another customisable approach that you can explore is to simply divide all values by the maximum value and take it to the power of a positive shape value ($\gamma$) that best satisfies your desired tranformation objectives. See example below in R in which the dashed line is the simple case of dividing x by max(x):
scaled_power_transform <- function(x, gamma=0.25)
{
    ## x must be nonnegative
    stopifnot(all(x >= 0))
    ## scale to [0, 1]
    x_scaled <- x / max(x)
    ## customise the shape
    x_scaled <- x_scaled^gamma
    return(invisible(x_scaled))
}



x <- seq(0, 1000)

plot(x = x,  y = scaled_power_transform(x, gamma = 0.1), col = 'blue',  
     type = 'l', lwd = 2, ylab = 'x transformed')
lines(x, x/max(x), lty = 2)
lines(x = x, y = scaled_power_transform(x, gamma = 0.5), col = 'green', 
      type = 'l', lwd = 2)
lines(x = x, y = scaled_power_transform(x, gamma = 2), col = 'red',   
      type = 'l', lwd = 2)

legend(x = 0.6*max(x), y=0.3, 
       legend = c(expression(paste(gamma,'= 0.1')), 
                  expression(paste(gamma,'= 0.5')), 
                  expression(paste(gamma,'= 2.0'))), 
       pch = rep('*', 3), col = c('blue', 'green', 'red'))


Created on 2020-10-10 by the reprex package (v0.3.0)
A: Any sigmoid function will work:


*

*The top half of the logistic function (multiply by 2, subtract 1)

*The error function

*tanh, as suggested by Henrik.

A: There are two ways to implement this that I use commonly. I am always working with realtime data, so this assumes continuous input. Here's some pseudo-code:
Using a trainable minmax:
define function peak:
    // keeps the highest value it has received

define function trough:
    // keeps the lowest value it has received

define function calibrate:
    // toggles whether peak() and trough() are receiving values or not

define function scale:
    // maps input range [trough.value() to peak.value()] to [0.0 to 1.0]

This function requires that you either perform an initial training phase (by using calibrate()) or that you re-train either at certain intervals or according to certain conditions. For instance, imagine a function like this:
define function outBounds (val, thresh):
    if val > (thresh*peak.value()) || val < (trough.value() / thresh):
        calibrate()


peak and trough are normally not receiving values, but if outBounds() receives a value that is more than 1.5 times the current peak or less than the current trough divided by 1.5, then calibrate() is called which allows the function to re-calibrate automatically.

Using an historical minmax:
var arrayLength = 1000
var histArray[arrayLength]

define historyArray(f):
    histArray.pushFront(f) //adds f to the beginning of the array

define max(array):
    // finds maximum element in histArray[]
    return max

define min(array):
    // finds minimum element in histArray[]
    return min

define function scale:
    // maps input range [min(histArray) to max(histArray)] to [0.0 to 1.0]

main()
historyArray(histArray)
scale(min(histArray), max(histArray), histArray[0])
// histArray[0] is the current element

A: My earlier post has a method to rank between 0 and 1. Advice on classifier input correlation
However, the ranking I have used, Tmin/Tmax uses the sample min/max but you may find the population min/max more appropriate. Also look up z scores
A: To add to the other answers suggesting pnorm...
For a potentially optimal method for selecting parameters I suggest this approximation for pnorm.
1.0/(1.0+exp(-1.69897*(x-mean(x))/sd(x)))


This is essentially Softmax Normalization.
Reference 
Pnorm in a pinch
A: A very simple option is dividing each number in your data by the largest number in your data.  If you have many small numbers and a few very large ones, this might not convey the information well.  But it's relatively easy; if you think meaningful information is lost when you graph the data like this, you could try one of the more sophisticated techniques that others have suggested.
A: there's a simple formula for normalization in $[0,1]$:
$$
x' = \begin{cases}
\frac{1}{ 1 + 1 / x  } & \text{if } x > 0\\ 0 & \text{else}
\end{cases}
$$
$$\lim_{x\rightarrow0} x' = 0$$
$$\lim_{x\rightarrow\infty} x' = 1$$
$$\lim_{x\rightarrow1} x' = 0.5$$
Is there a name for this function?
