2008-10-14 18:37:17 8 Comments

How can you round *any* number (not just integers > 0) to N significant digits?

For example, if I want to round to three significant digits, I'm looking for a formula that could take:

1,239,451 and return 1,240,000

12.1257 and return 12.1

.0681 and return .0681

5 and return 5

Naturally the algorithm should not be hard-coded to only handle N of 3, although that would be a start.

### Related Questions

#### Sponsored Content

#### 24 Answered Questions

### [SOLVED] Image Processing: Algorithm Improvement for 'Coca-Cola Can' Recognition

**2012-04-16 04:23:16****Charles Menguy****161657**View**1508**Score**24**Answer- Tags: c++ algorithm image-processing opencv

#### 63 Answered Questions

### [SOLVED] Round to at most 2 decimal places (only if necessary)

**2012-08-06 17:17:48****stinkycheeseman****1889413**View**2145**Score**63**Answer- Tags: javascript decimal rounding decimal-point

#### 27 Answered Questions

#### 43 Answered Questions

#### 35 Answered Questions

### [SOLVED] Given a number, find the next higher number which has the exact same set of digits as the original number

**2012-02-20 20:50:03****bhan****70804**View**219**Score**35**Answer- Tags: algorithm

#### 6 Answered Questions

### [SOLVED] Ukkonen's suffix tree algorithm in plain English

**2012-02-26 11:30:09****Nathan Ridley****146665**View**1024**Score**6**Answer- Tags: string algorithm language-agnostic suffix-tree

#### 29 Answered Questions

#### 4 Answered Questions

#### 11 Answered Questions

### [SOLVED] Round a double to x significant figures

**2008-12-17 11:52:09****Rocco****52875**View**55**Score**11**Answer- Tags: c# math rounding significant-digits

#### 1 Answered Questions

### [SOLVED] Round to significant digits *only* with decimal portion of number in R

**2017-03-27 15:47:35****Andrew****1021**View**2**Score**1**Answer- Tags: r rounding significant-digits

## 17 comments

## @Michael Hampton 2018-01-28 02:42:21

I needed this in Go, which was a bit complicated by the Go standard library's lack of

`math.Round()`

(before go1.10). So I had to whip that up too. Here is my translation of Pyrolistical's excellent answer:## @Michael Hampton 2018-08-28 17:35:11

This got a mystery downvote! But I can't find an error or problem in it. What's going on here?

## @Duncan Calvert 2017-03-27 16:22:43

`return new BigDecimal(value, new MathContext(significantFigures, RoundingMode.HALF_UP)).doubleValue();`

## @Zaz 2015-05-04 22:56:25

## JavaScript:

The

`Number`

function will change output of the form`"8.143e+5"`

to`"814300"`

.## @Pyrolistical 2009-10-17 00:20:15

Here's the same code in Java without the 12.100000000000001 bug other answers have

I also removed repeated code, changed

`power`

to a type integer to prevent floating issues when`n - d`

is done, and made the long intermediate more clearThe bug was caused by multiplying a large number with a small number. Instead I divide two numbers of similar size.

EDITFixed more bugs. Added check for 0 as it would result in NaN. Made the function actually work with negative numbers (The original code doesn't handle negative numbers because a log of a negative number is a complex number)

## @Claudiu 2009-12-14 23:41:53

Your code is indeed much nicer.

## @Pyrolistical 2010-05-21 22:45:41

Thanks for accepting my answer. I just realized my answer is more than a year after the question. This is one of the reasons why stackoverflow is so cool. You can find useful information!

## @cquezel 2014-11-22 17:10:15

Note that this may fail slightly for values close to the round limit. For example rounding 1.255 to 3 significant digits should return 1.26 but returns 1.25. That is because 1.255 * 100.0 is 125.499999... But this is to be expected when working with doubles

## @Steve W 2016-01-20 15:04:38

Wow, I know this is old, but I'm trying to use it. I have a float that I want to display to 3 significant figures. If the float value is 1.0, I call your method but it still returns as 1.0, even if I cast the float as a double. I want it to return as 1. Any ideas?

## @Curious Sam 2016-02-18 15:11:59

This java snippet ends up in official android example android.googlesource.com/platform/development/+/fcf4286/samples/…

## @Pyrolistical 2016-03-08 22:40:21

lol nice find @CuriousSam

## @Duncan Calvert 2017-03-24 18:01:23

Not perfect. For num = -7999999.999999992 and n = 2 returns -7999999.999999999 but should be -8000000.

## @Eric Nicolas 2017-05-26 12:28:06

I tested on +7999999.999999992 and it gives +8000000 ok. I think negative numbers should be treated by a special case, as is zero, for safety.

## @JackDev 2013-10-22 00:07:22

This came 5 years late, but though I'll share for others still having the same issue. I like it because it's simple and no calculations on the code side. See Built in methods for displaying Significant figures for more info.

This is if you just want to print it out.

This is if you want to convert it:

Here's an example of it in action:

## @matt 2019-03-10 09:27:45

This will display "big" numbers in scientific notation, e.g. 15k as 1.5e04.

## @SomeGuy 2013-06-01 16:05:51

This is one that I came up with in VB:

## @Harikrishnan 2013-05-19 05:51:47

This code uses the inbuilt formatting function which is turned to a rounding function

## @Michael Zlatkovsky - Microsoft 2011-06-21 16:10:45

Here is Pyrolistical's (currently top answer) code in Visual Basic.NET, should anyone need it:

## @Thomas Becker 2010-11-19 01:17:06

Pyrolistical's (very nice!) solution still has an issue. The maximum double value in Java is on the order of 10^308, while the minimum value is on the order of 10^-324. Therefore, you can run into trouble when applying the function

`roundToSignificantFigures`

to something that's within a few powers of ten of`Double.MIN_VALUE`

. For example, when you callthen the variable

`power`

will have the value 3 - (-309) = 312. Consequently, the variable`magnitude`

will become`Infinity`

, and it's all garbage from then on out. Fortunately, this is not an insurmountable problem: it is only thefactor`magnitude`

that's overflowing. What really matters is theproduct`num * magnitude`

, and that does not overflow. One way of resolving this is by breaking up the multiplication by the factor`magintude`

into two steps:## @Pyrolistical 2012-05-07 18:30:42

Whoa, rounding at the edge of the universe!

## @wolfgang grinfeld 2010-08-10 08:00:42

How about this java solution :

## @Valeri Shibaev 2010-06-22 00:25:30

## @Jason Swank 2010-06-04 16:18:40

Here is a modified version of Ates' JavaScript that handles negative numbers.

## @Claudiu 2008-10-14 18:47:01

SUMMARY:

So you need to find the decimal place of the first non-zero digit, then save the next N-1 digits, then round the Nth digit based on the rest.

We can use log to do the first.

So for numbers > 0, take the ceil of the log. For numbers < 0, take the floor of the log.

Now we have the digit

`d`

: 7 in the first case, 2 in the 2nd, -2 in the 3rd.We have to round the

`(d-N)`

th digit. Something like:Then do the standard rounding thing:

And undo the pow.

Where power is the power calculated above.

About accuracy: Pyrolistical's answer is indeed closer to the real result. But note that you can't represent 12.1 exactly in any case. If you print the answers as follows:

The answers are:

So, use Pyro's answer!

## @Ates Goral 2008-10-14 19:30:23

This algorithm seems prone to floating point errors. When implemented with JavaScript, I get: 0.06805 -> 0.06810000000000001 and 12.1 -> 12.100000000000001

## @Claudiu 2008-10-15 01:28:48

12.1 by itself can't be represented accurately using floating point - it's not a result of this algorithm.

## @Pyrolistical 2009-10-17 00:00:27

This code in Java produces 12.100000000000001 and this is using 64-bit doubles which can present 12.1 exactly.

## @Claudiu 2009-10-17 17:02:00

It doesn't matter if it's 64 bit or 128 bit. You can't represent the fraction 1/10 using a finite sum of powers of 2, and that's how floating point numbers are represented

## @Claudiu 2011-03-06 05:20:37

for those chiming in, basically Pyrolistical's answer is more precise than mine so that the floating point number printing algorithm prints '12.1' instead of '12.100000000000001'. his answer is better, even tho i was technically correct that you can't represent '12.1' exactly.

## @David R Tribble 2009-10-17 00:41:19

[Corrected, 2009-10-26]Essentially, for N significant

fractionaldigits:• Multiply the number by 10

^{N}• Add 0.5

• Truncate the fraction digits (i.e., truncate the result into an integer)

• Divide by 10

^{N}For N significant

integral(non-fractional) digits:• Divide the number by 10

^{N}• Add 0.5

• Truncate the fraction digits (i.e., truncate the result into an integer)

• Multiply by 10

^{N}You can do this on any calculator, for example, that has an "INT" (integer truncation) operator.

## @Pyrolistical 2009-10-20 18:06:49

Nope. Read the question again. 1239451 with 3 sig figs using your algorithm would incorrectly yield 123951

## @David R Tribble 2009-10-26 21:53:42

Yep, I corrected it to distinguish between rounding to a

fractionalnumber of digits (to the right of the decimal point) versus anintegralnumber of digits (to the left).## @Justin Wignall 2009-04-08 15:26:57

Isn't the "short and sweet" JavaScript implementation

e.g.

?

Sorry, I'm not being facetious here, it's just that using the "roundit" function from Claudiu and the .toPrecision in JavaScript gives me different results but only in the rounding of the last digit.

JavaScript:

.NET

## @Zaz 2015-05-04 22:48:44

`Number(814301).toPrecision(4) == "8.143e+5"`

. Generally not what you want if you're showing this to users.## @Justin Wignall 2015-05-05 19:53:32

Very true Josh yes, I would generally recommend .toPrecision() only for decimal numbers and the accepted answer (with edit) should be used/reviewed as per your individual requirements.

## @Ates Goral 2008-10-14 19:20:32

Here's a short and sweet JavaScript implementation:

## @Pyrolistical 2009-10-17 00:03:07

but 12.1257 gives 12.126

## @Ates Goral 2009-10-17 22:47:47

Yes, that's valid rounding.

## @sscirrus 2011-10-22 01:56:27

Nice answer Ates. Perhaps add a trigger to return 0 if

`n==0`

:)## @Mahn 2014-04-01 20:20:55

PHP port for the lazy: gist.github.com/anonymous/9922298

## @Lee 2015-10-23 01:03:26

is there a reason to do

`Math.log(n) / Math.LN10`

rather than`Math.log10(n)`

?## @Ates Goral 2015-10-23 03:58:01

@Lee developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… "This is a new technology, part of the ECMAScript 2015 (ES6) standard." So, basically, compatibility issues.

## @Paul 2018-02-28 12:09:51

Am I missing something, or does this answer assume that

`Math.floor(x) == Math.ceil(x) - 1`

? Because it doesn't when`x`

is an integer. I think the second argument of the`pow`

function should be`sig - Math.ceil(Math.log(n) / Math.LN10)`

(or just use`Math.log10`

)## @Mark Bessey 2008-10-14 18:52:37

Have you tried just coding it up the way you'd do it by hand?