So in this post I will be taking a look at the Math.round method, but also additional options, user space alternatives, and any related topics that might come up when it comes to formatting numbers for the sake of presentation.
Maybe the best way to start out with this is to just call the various methods and pass some number literals to then just for the sake of confirming that they work as advertised. For example If I feed the number 1.005 as the argument for each methods I would expect 1 for Math.round, 2 for Math.ceil, and 1 for Math.floor.
Okay so far so good, then one might think that these methods will work just fine for rounding, and there is nothing more to be aware of beyond that. I can just use one of these methods to round numbers when and where needed and that is it, no need for a long from blog post for this one then right?
In this example I am using the Math.round method to return a 0 or 1 based on rounding the result of a random value using the Math.random method. The random method will return a number between 0 and 1, and can include 0 but not 1 at least from what I have read about that.
So then my random bit method is just a simple one line expression there I am passing the return vaalue of a Math.random call as the value to round for the Math.round method. In the event that the random value is greater than or equal to 0.5 it will return 1, else 0.
Using Math.ceil is useful for some situations in which I will always want to round up with any fraction value to the next whole number. For this example I made a quick function that will take a cost of something apply a markup to it and then use Math.ceil to round up, rather than down always to the next whole number. After that I just subtract one cent from the value to get a subtest shelf price for some kind of item in a hypothetical store.
The Math.floor method is one of the round methods that I seem to use most of the time. One reason why is because it is a good choice when it comes to making a quick method that has to do with getting a random element in an array. The reason why I say that might have to do with the nature of the Math.random method combined with the zero relative index numbers of arrays. As I mentioned in a previous example the return value of a Math.random call will be between 0, and 1, and can potential also include 0, but not 1. So then if I multiply the random value returned by the Math.random method by the length of an array, and then pass that to the Math.floor method, the end result should always be a random element index that is not outside the length of the array.
If I where to replace the call of Math.floor with Math.round, or Math.ceil the result would be the occasion reference to an element outside the range of the array which will result in an undefined value.
There is also getting a random point in an area that has a width and height that comes to mind when rounding. For this example I made a quick function that will take a width and height value as the first two arguments, and then values between 0 and one for with and height. The returned result is then an object with x and y values that are placed between the width and hight value multiplied by the percent values, and then rounded using the Math.floor method.
So when it comes to just simply formatting a string representation of a number for the sake of display in a view maybe this will works okay in most situations. Still for the fact that it returns a string, and also because it does not round right all the time, this causes me to look for yet another solution for rounding. When all else fails look for a user space solution I guess, and if I can find something there is also doing my own thing.
When it comes to numbers that a greater than zero, numbers that have a fraction of one half on the nose are rounded up. This does not just apply with numbers above zero though. In general all numbers will round up to positive infinity rather than negative infinity. There is no distinction made for negative numbers with Math.round, but do not just take my worth for it play around with a few simple examples feeding some number literals to confirm it to yourself first hand.
If for some reason this is a problem I guess this might be another thing that can come up that might require a need for a user space solution for rounding numbers.
If a number between and including -0.5 and zero is given this can result in negative zero being the return value. This can present a problem with using the Object.is method, or any other method that makes use of Object.is or produced the same kind of comparison often called Same Value Zero such as the _.eq method, and many other methods in lodash.
It is not so hard to work out a fix for numbers flowing to positive infinity rather than negative infinity if it is a problem. Addressing the negative zero thing can also be addressed in the process of doing so, and this is then one of the reasons why one might be inclined to make a custom rounding method.
Looks like I found my copy and past user space solution for rounding rather than bothering with lodash for just that one method. This gives me the functionally that I like in the Number.toFIxed method but without the weird issue that results in wrong rounding.
So then there is using the custom method that I found for rounding with a precision value, but also working in some more stuff that I would like to have working for me each time I round a number. This will then result in a method that does not just round, but also preforms a number of additional things that have to do with formating a number.
Yet another option for rounding would be to use the Internationalization API, main the Number Format method. This can be used to not just round, but also format a string value for the purpose of displaying with respect to the typical formats for money. For example if I have a value that is a number value that is an amount of money, when it comes to displaying that I might want to round, but for a precision value two two decimal places not a whole number. On top of that I might also want to have a comma between each three digits of the whole number part of the value also. I could come up with or fine some kind of user space solution for this, however it would seem that there is a native method that can be used for this in the Internationalization API.
When using the Intl.NumberFormat constructor the first argument that I need to give is a language code, for me this is ‘en-us’, after that I give an object with a bunch of options for this method. The main value that I will want to set are the style which I would want to set to ‘currency’ for money, and again for my language code I would want to use ‘USD’ for the currency. For the most part I would want to use the default settings for the precision, but if I want to adjust that there is the minimum fractiondDigits and maximum fraction digits properties that I can use for that. The return value for calling the constructor is then not a string, but an object that contains a few options for formating, including one that will return a string.
So there are a few built in options for rounding in the Math object, and also certain prototype methods in other built in Objects and classes that help with rounding. However sometimes it makes sense to go with a user space solution for rounding, and formatting a number in general for presentation also. However maybe it can be said that these kinds of situations can be avoided when it comes to the issues with rounding negative numbers and so forth. When it comes to the negative zero situation there is just using the older equality and identity operators that will still return what many might see as an expected result for that kind of situation. However there is knowing what the deal is with it when it comes to what is going on, and why negative zero is not really the same thing as positive zero, so then when that is the case that is where things can be a little involved.