Normalize a given random value to the range of 0 - 1 in java

8.3k views Asked by At

Say i get a value that is a difference of current time in milliseconds - some datetime in milliseconds.

double value = Calendar.getInstance().getTimeInMillis() - getMilliseconds(reportingDt);

So this would be a quite a big value. Now i want to normalize it to a scale of 0 - 1.

Please can some one suggest how can this be achieved in java, so that my value is scaled in between 0 and 1.

The more recent is the reportingDt more the final value is towards 1 and older the reportingDt more it is towards 0.

UPDATE

Well my approach towards normalizing it was as below. This is more of a prototype, but it worked for me.

private double getDocumentScore(String reportingDt) {

        Date offset = null;
        try {
            offset = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS").parse("24-08-2017 13:53:30.802");
        } catch (ParseException e) {
            e.printStackTrace();
        } 

        long currentTime = Calendar.getInstance().getTimeInMillis(); 
        if(offset != null) {
            // If offset is set then instead of current datetime consider offset
            currentTime = offset.getTime();
        }
        System.out.println(reportingDt);
        long value = currentTime - getMilliseconds(reportingDt);

        long minutes = TimeUnit.MILLISECONDS.toMinutes(value);
        double score = 2 * (1 / Math.log(minutes));
        System.out.println(score);
        return score;
    }

    private long getMilliseconds(String dateTime) {
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS");
        Date date = null;
        try {
            date = formatter.parse(dateTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date.getTime();
    }

Sample input date and output normalized score values were

11-07-2017 14:34:05.416
0.18089822028334113
11-07-2017 14:34:06.023
0.18089822028334113
11-07-2017 14:34:06.595
0.18089822028334113
11-07-2017 14:34:07.139
0.18089822028334113
11-07-2017 14:34:08.873
0.18089822028334113
11-07-2017 14:34:11.171
0.18089822028334113
11-07-2017 14:34:12.954
0.18089822028334113
11-07-2017 14:34:12.962
0.18089822028334113
11-07-2017 14:34:34.516
0.18089847869291217
11-07-2017 14:34:35.720
0.18089847869291217
11-07-2017 14:34:38.566
0.18089847869291217
11-07-2017 14:34:39.205
0.18089847869291217
11-07-2017 14:34:40.357
0.18089847869291217

Below is the graph plot for various score function i considered to normalize the value. Finally i used green line one (2* (1/log(x)))

enter image description here

3

There are 3 answers

1
a_a On

Do like this-

double currenttime=Calendar.getInstance().getTimeInMillis();    
double value= currenttime- getMilliseconds(reportingDt);
double normalized=(1- value/currenttime;
System.out.println(normalized);
0
gufidown On

Sorry, that's impossible to solve. Why? Because time moves on and you would get different values for the very same DateTime value, depending on whether you execute your code today, tomorrow, in a year from now ...

You would have to have a fixed time range that you want to observe. If you say you wanna go from Jan 1st 1970 to Jan 1st 2070 you could simply divide your timespan's value by this maximum timespan value. Subtract 1 from it and set the result absolute. But this result will approach 1 only in the 60ies of this century. It is not really what you were asking for.

Then, on the other side, what's the use of having a floating point number with lots of digits behind the comma as opposed to a long value with lots of digits in front of the comma?

0
DodgyCodeException On

You said you can put all the values in a list and calculate the minimum and maximum values. Then each value can be normalized like this:

/**
 * Calculates a value between 0 and 1, given the precondition that value
 * is between min and max. 0 means value = max, and 1 means value = min.
 */
double normalize(double value, double min, double max) {
    return 1 - ((value - min) / (max - min));
}