133


Can someone give me an idea how can i round off a number to the nearest 0.5.
I have to scale elements in a web page according to screen resolution and for that i can only assign font size in pts to 1, 1.5 or 2 and onwards etc.

If i round off it rounds either to 1 decimal place or none. How can i accomplish this job?

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
Johnydep
  • 6,027
  • 20
  • 57
  • 74

10 Answers10

254

Write your own function that multiplies by 2, rounds, then divides by 2, e.g.

function roundHalf(num) {
    return Math.round(num*2)/2;
}
saeraphin
  • 395
  • 1
  • 9
newtron
  • 5,938
  • 1
  • 23
  • 19
  • Just used this to clean up a reduce function on monetary values that was coming back with like 9 decimal points... (num*100)/100 worked perfectly. – Dustin Kreidler Feb 12 '19 at 16:53
  • If you want to end up with either 13.0 or 13.5, I combined your answer with the one below: function roundHalf(num) { return (Math.round(num*2)/2).toFixed(1); } – Dan D Jun 29 '19 at 18:04
  • 1
    rounding the num*2 is not working for all case..try any decimal like 15.27 => using your formula will give => 15 where in fact it should have returned 15.5. **** I think using toFixed will be better (num*2).toFixed()/2 – sfdx bomb Dec 02 '19 at 16:12
  • 4
    @sfdxbomb Have you checked this? In my browser's console `roundHalf(15.27)` returns 15.5 – malarres Aug 28 '20 at 11:04
115

Here's a more generic solution that may be useful to you:

function round(value, step) {
    step || (step = 1.0);
    var inv = 1.0 / step;
    return Math.round(value * inv) / inv;
}

round(2.74, 0.1) = 2.7

round(2.74, 0.25) = 2.75

round(2.74, 0.5) = 2.5

round(2.74, 1.0) = 3.0

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Michael Deal
  • 2,948
  • 2
  • 18
  • 8
13

Just a stripped down version of all the above answers:

Math.round(valueToRound / 0.5) * 0.5;

Generic:

Math.round(valueToRound / step) * step;
cela
  • 2,352
  • 3
  • 21
  • 43
Paul Lee
  • 131
  • 1
  • 3
5

To extend the top answer by newtron for rounding on more than only 0.5

function roundByNum(num, rounder) {
    var multiplier = 1/(rounder||0.5);
    return Math.round(num*multiplier)/multiplier;
}

console.log(roundByNum(74.67)); //expected output 74.5
console.log(roundByNum(74.67, 0.25)); //expected output 74.75
console.log(roundByNum(74.67, 4)); //expected output 76

3

Math.round(-0.5) returns 0, but it should be -1 according to the math rules.

More info: Math.round() and Number.prototype.toFixed()

function round(number) {
    var value = (number * 2).toFixed() / 2;
    return value;
}
URL87
  • 10,667
  • 35
  • 107
  • 174
Julia Savinkova
  • 573
  • 8
  • 18
  • 1
    @Yuri To expand on what you're saying, `round` rounds to the next integer greater than the given value, which in terms of negative numbers would be towards the positive integer spectrum. -2.5 would go to -2. Is that correct? – Danny Bullis Nov 23 '15 at 22:44
  • Yup just verified. `Math.ceil(-1.75) == -1` and `Math.floor(-1.75) == -2`. So for anyone getting tripped up by this, just think of it as `ceil` returns a **greater than** number, `floor` returns a **less than** number. – Danny Bullis Nov 23 '15 at 22:46
  • Rounding -0.5 does equal 0. – Dan Oct 28 '22 at 20:23
2

The highest voted answer above fails for:

  • roundHalf(0.6) => returns 0.5
  • roundHalf(15.27) => returns 15.5

The fixed one is as follows:

   const roundHalf = (num) => {
      return Math.floor(Math.ceil(num * 2) / 2)
    }
Omer Gurarslan
  • 979
  • 11
  • 15
1
    function roundToTheHalfDollar(inputValue){
      var percentile = Math.round((Math.round(inputValue*Math.pow(10,2))/Math.pow(10,2)-parseFloat(Math.trunc(inputValue)))*100)
      var outputValue = (0.5 * (percentile >= 25 ? 1 : 0)) + (0.5 * (percentile >= 75 ? 1 : 0))
      return Math.trunc(inputValue) + outputValue
    }

I wrote this before seeing Tunaki's better response ;)

mekdigital
  • 381
  • 3
  • 8
1
var f = 2.6;
var v = Math.floor(f) + ( Math.round( (f - Math.floor(f)) ) ? 0.5 : 0.0 );
Blazes
  • 4,721
  • 2
  • 22
  • 29
1

These answers weren't useful for me, I wanted to always round to a half (so that drawing with svg or canvas is sharp).

This rounds to the closest .5 (with a bias to go higher if in the middle)

function sharpen(num) {
  const rem = num % 1
  if (rem < 0.5) {
    return Math.ceil(num / 0.5) * 0.5 + 0.5
  } else {
    return Math.floor(num / 0.5) * 0.5
  }
}

console.log(sharpen(1)) // 1.5
console.log(sharpen(1.9)) // 1.5
console.log(sharpen(2)) // 2.5
console.log(sharpen(2.5)) // 2.5
console.log(sharpen(2.6)) // 2.5
Dominic
  • 62,658
  • 20
  • 139
  • 163
0

As a bit more flexible variation of the good answer above.

function roundNumber(value, step = 1.0, type = 'round') {
  step || (step = 1.0);
  const inv = 1.0 / step;
  const mathFunc = 'ceil' === type ? Math.ceil : ('floor' === type ? Math.floor : Math.round);

  return mathFunc(value * inv) / inv;
}