Title: **Rounding to an Arbitrary number of Significant Digits.**

Post by:**GWS** on **May 13, 2013, 02:00:43 am**

Post by:

Hi,

Here's a little problem I came across while working on a current project - how to round a number to a given number of significant digits.

That should be easy, I thought. For example I wanted a number like 12.1257 to return 12.1

After screwing my brains into a knot, I got some clunky code working (which I won't for shame reveal), except to say, it involved a lot of string handling of the Val() to Str$() to Val() type. ::)

How difficult could a simple operation be?

Fortunately, my daughter is an expert Googler, found this discussion in some java - C hieroglyphics, which I think I've managed to translate into the much easier to read Basic code.

Anyway, here's the test program I've concocted, to take any positive, non-zero number, and re-map it to a given number of significant figures. I was interested in 2 or 3 figures for my application. :)

Look at that lovely little subroutine - is that smart or what?

I'm still not sure I understand how it does it - but it works! ;D

If you would like to read the discussion about this, you can find it here ..

http://stackoverflow.com/questions/202302/rounding-to-an-arbitrary-number-of-significant-digits (http://stackoverflow.com/questions/202302/rounding-to-an-arbitrary-number-of-significant-digits)

All the best, :)

Graham

Here's a little problem I came across while working on a current project - how to round a number to a given number of significant digits.

That should be easy, I thought. For example I wanted a number like 12.1257 to return 12.1

After screwing my brains into a knot, I got some clunky code working (which I won't for shame reveal), except to say, it involved a lot of string handling of the Val() to Str$() to Val() type. ::)

How difficult could a simple operation be?

Fortunately, my daughter is an expert Googler, found this discussion in some java - C hieroglyphics, which I think I've managed to translate into the much easier to read Basic code.

Anyway, here's the test program I've concocted, to take any positive, non-zero number, and re-map it to a given number of significant figures. I was interested in 2 or 3 figures for my application. :)

Code Select

' Rounding to a given number of significant figures ..

' GWS - 2013

openconsole

cls

autodefine = "off"

setprecision 5

def n:int

def x,r:double

declare Round(value:double,nfigs:int)

' some test values ..

x = 12.1257

'x = 4855600

'x = 2008

'x = 0.0681

'x = .55578

'x = 1.50666

'x = 27460

'x = 635.89

r = Round(x,3)

print "rounded = ",r

do:until inkey$<>""

closeconsole

end

sub Round(value,nfigs)

def ret,d:double

' routine to round a value to 'n' significant figures ..

if (value = 0)

ret = 0

else

d = ceil(log10(value))

n = -(d - nfigs)

ret = int(value * 10^n + 0.5) * 10^-n

endif

return ret

Look at that lovely little subroutine - is that smart or what?

I'm still not sure I understand how it does it - but it works! ;D

If you would like to read the discussion about this, you can find it here ..

http://stackoverflow.com/questions/202302/rounding-to-an-arbitrary-number-of-significant-digits (http://stackoverflow.com/questions/202302/rounding-to-an-arbitrary-number-of-significant-digits)

All the best, :)

Graham

Title: **Re: Rounding to an Arbitrary number of Significant Digits.**

Post by:**Kian** on **May 13, 2013, 12:55:39 pm**

Post by:

Hi Graham,

This ensures that '0' is not passed to the logarithm function as log(0) is undefined.

This returns how many digits there are before the decimal point, using the 'ceil' function to ensure rounding up.

(e.g. log(12.345) is 1.0914911 because it is between 10^1 and 10^2, and this is rounded up to 2)

Values below zero give a negative result for this.

('nfigs-d' would probably save a cycle or two)

This calculates how many columns to shift the digits for the purposes of rounding.

(e.g. to find 12.345 to 3 s.f. it should be shifted 1 column to the left to round after the 3)

The 'value * 10^n' performs the shift, i.e. turns 12.345 into 123.45

and the 0.5 is added to ensure that the 'int' function rounds anything from .5 and higher upwards.(leaving 123 in the above example)

Finally, the '* 10^-n' reverses the shift.(leaving 12.3 above)

Rather long-winded, but as concise an explanation as I can manage at this time of night.

Kian

QuoteI'm still not sure I understand how it does it

Code Select

`if (value = 0)`

This ensures that '0' is not passed to the logarithm function as log(0) is undefined.

Code Select

`d = ceil(log10(value))`

This returns how many digits there are before the decimal point, using the 'ceil' function to ensure rounding up.

(e.g. log(12.345) is 1.0914911 because it is between 10^1 and 10^2, and this is rounded up to 2)

Values below zero give a negative result for this.

Code Select

`n = -(d - nfigs)`

('nfigs-d' would probably save a cycle or two)

This calculates how many columns to shift the digits for the purposes of rounding.

(e.g. to find 12.345 to 3 s.f. it should be shifted 1 column to the left to round after the 3)

Code Select

`ret = int(value * 10^n + 0.5) * 10^-n`

The 'value * 10^n' performs the shift, i.e. turns 12.345 into 123.45

and the 0.5 is added to ensure that the 'int' function rounds anything from .5 and higher upwards.(leaving 123 in the above example)

Finally, the '* 10^-n' reverses the shift.(leaving 12.3 above)

Rather long-winded, but as concise an explanation as I can manage at this time of night.

Kian

Title: **Re: Rounding to an Arbitrary number of Significant Digits.**

Post by:**GWS** on **May 13, 2013, 04:56:36 pm**

Post by:

Thanks Kian, ;D .. that's a great explanation.

You're right - I should have spotted the double negative .. 'nfigs-d' is much neater :)

I like that little subroutine - it does all the work in 3 lines, where my sledgehammer method was taking more than a page of code. ::)

All the best, :)

Graham

You're right - I should have spotted the double negative .. 'nfigs-d' is much neater :)

I like that little subroutine - it does all the work in 3 lines, where my sledgehammer method was taking more than a page of code. ::)

All the best, :)

Graham