top of page
Search
  • Writer's picturegirizano

Commercial (psychological) rounding

Abstract

In this contribution, we publish an algorithm for commercial (psychological) rounding. So what is that?


The problem: two ways of rounding

Rounding is a poorly understood art. As far as I can see, there are two ways of rounding:

1) "multiples of": lets say you want to round "123" Up to it´s nearest "50". That would be "150". But if you do the same for "176", it would be "200". Now, this is called "multiples off"-rounding: 200 is a multiple of 50, but.... it was not was I was looking for. It doesn´t END on "50", does it? I wanted something that always, always, calculated a price ENDING on something. Like .99, .98, .50, 50, 75, 100, whatever. Well, that´s another kind of rounding, and it is called

2) commercial (psychological) rounding: this kind of rounding gives you commercial (psychological) pricing. So, what´s the difference? Well, let´s do an example. Say we want to round 1.86 up to (a multiple of) 0.99. You would expect 1.99. But it gives you 1.98 (2 multiples of 0.99). It doesn´t end on .99, so that is not what we want.

Read on for the solution to this problem.


Caveat, user

This is new, and it is not trivial (well, at least not to me). I spent more time walking up and down the lawn frowning my face and thinking "How do I solve this" than I spent on coding it. It´s the first working version, I tested it and I think it works, but that´s what we all think, and it usually doesn´t. So if you find a glitch in the Matrix, please let me know, I´ll try to fix it (I am using it myself too and I can only benefit from it).

Code is documented, as best as I could, inline.


The code

Put the following code inside a Wix normal page. Run it, play with it and look at the Wix Console (or the browser´s console) for results. Good luck.


$w.onReady(function () { console.log("1321 rounded Up on 75 = " + fnRoundAmount(1321, 75, 0)); console.log("1321 rounded Up on 99 = " + fnRoundAmount(1321, 99, 0)); console.log("1321 rounded Up on 98 = " + fnRoundAmount(1321, 98, 0)); console.log("1381 rounded Down on 100 = " + fnRoundAmount(1381, 100, 1)); console.log("1381 rounded Arith on 100 = " + fnRoundAmount(1381, 100, 2)); console.log("1321 rounded Down on 100 = " + fnRoundAmount(1321, 100, 1)); console.log("1321 rounded Arith on 100 = " + fnRoundAmount(1321, 100, 2)); console.log("187.50 rounded Up on 1 = " + fnRoundAmount(187.5, 1, 0)); console.log("187.50 rounded Down on 1 = " + fnRoundAmount(187.5, 1, 1)); console.log("187.50 rounded Arith on 1 = " + fnRoundAmount(187.5, 1, 2)); console.log("0.43 rounded Up on 0.99 = " + fnRoundAmount(0.43, 0.99, 0)); console.log("0.43 rounded Down on 0.99 = " + fnRoundAmount(0.43, 0.99, 1)); });



function fnRoundAmount(numAmountIn, numRoundOn, numRoundType) { //Rounds a number Up, Down or Up/Down arithmetically on a certain amount. Call it like: //fnRoundAmount(1321, 75, 0). It will return 1375 //numRoundOn may be greater than numAmountIn (like round 0.43 up to 0.99). Values for numRoundType //are:0=Up,1=Down,2=arithmetically let numDiv = numAmountIn / numRoundOn; //devide amount by number to round on. You will get some float let numFactor = fnFindFactor (numRoundOn); // find nearest 1, 10, 100 etc to calculate back from /* Below a list of outcomes. The factor is the amount which, if we subtract (Factor-Roundon) from it, we get the correct Rounding. Example : Round on 99, means Factor = 100. Later on, we do: 100-99=1. Then, after first Rounding to nearest Amnount, we subtract this 1 from the amount to come up with 99. Round on Factor 500 1000 99 100 100 100 9 10 0.95 1 */ let numMod = numAmountIn % numRoundOn; // calc modulo if we have to do Arithmatic rounding let numModDivByUnit = numMod / numRoundOn; // devide mod by amount to round on let boolIsgeHalf = numModDivByUnit >= 0.5; // is it greater or equal than 0.5? Then Method is up for arithmetical let numBaseUp = Math.round(numDiv + 0.5); //round the division (amount/roundon) up for Up method let numBaseDown = Math.round(numDiv - 0.5); // same for Down /* Here we do the real calculation. First, we round Up/Down to the nearest number where Number % Factor = 0 Example: 1321 Round up on 75 becomes 1400 (nearest) - (100 (Factor) -75 (RoundOn)) = 1400 - 25, thus 1375 */ let numRoundedUp = fnRoundOnNearest(numBaseUp * numRoundOn, numFactor) - (numFactor - numRoundOn); /* Same for Down 1321 Round down on 75 becomes 1300 (nearest) - (100 (Factor) -75 (RoundOn)) = 1300 - 25, thus 1275 */ let numRoundedDown = fnRoundOnNearest(numBaseDown * numRoundOn, numFactor) - (numFactor - numRoundOn); switch (numRoundType) { case 0: // up return numRoundedUp; case 1: // down return numRoundedDown; case 2: // arithmetical if (boolIsgeHalf) { return numRoundedUp; } else return numRoundedDown; } } function fnRoundOnNearest(numAmount, numFactor) { // a provision for amounts like 0.49. Force at least 1 go inside the loop if (numAmount < 1) { numAmount = 1; } for (var i = numAmount; i <= numAmount + numFactor; i++) { // find first number which, Modulo´d by Factor, returns 0 if (i % numFactor === 0) { return i; } } } function fnFindFactor (numAmount) { /* The Factor is the nearest of a set of numbers which, when we subtract the rounding from the factor, and then subtract this result from the amount, we get the correct rounding. Example: 1321 Round up on 75. The factor for 75 = 100. Meaning: 100-75=25. When we subtract this number from the first calculated Base amount (1400), we get 1400-25 = 1375. */ //create an array. You could do this in a loop, but this is easier to read and enough for me // we simply compare the amount with each number as long as the amount is smaller or equal. Then we return the value as Factor let arrLimits = [1,10,100,1000,10000,100000,1000000,10000000,100000000] for (var i = 0; i < arrLimits.length; i++) { if (numAmount <= arrLimits[i]) { return arrLimits[i]; } } }





64 views0 comments

Recent Posts

See All
bottom of page