Domanda

I'm in need of a function returning only the significant part of a value with respect to a given error. Meaning something like this:

def (value, error):
    """ This function takes a value and determines its significant
        accuracy by its error.
        It returns only the scientific important part of a value and drops the rest. """

    magic magic magic....

    return formated value as String.

What i have written so far to show what I mean:

import numpy as np

def signigicant(value, error):
    """ Returns a number in a scintific format. Meaning a value has an error
        and that error determines  how many digits of the
        value are signifcant. e.g. value = 12.345MHz, 
        error = 0.1MHz => 12.3MHz because the error is at the first digit.
        (in reality drop the MHz its just to show why.)"""


    xx = "%E"%error    # I assume this is most ineffective.
    xx = xx.split("E")
    xx = int(xx[1])

    if error <= value: # this should be the normal case
        yy = np.around(value, -xx)

        if xx >= 0: # Error is 1 or bigger
            return "%i"%yy

        else: # Error is smaller than 1
            string = "%."+str(-xx) +"f"
            return string%yy

    if error > value: # This should not be usual but it can happen.
        return "%g"%value

What I don't want is a function like numpys around or round. Those functions take a value and want to know what part of this value is important. The point is that in general I don't know how many digits are significant. It depends in the size of the error of that value. Another example:

value = 123, error = 12, => 120 One can drop the 3, because the error is at the size of 10. However this behaviour is not so important, because some people still write 123 for the value. Here it is okay but not perfectly right.

For big numbers the "g" string operator is a usable choice but not always what I need. For e.g. If the error is bigger than the value.( happens e.g. when someone wants to measure something that does not exist.)

value = 10, error = 100

I still wish to keep the 10 as the value because I done know it any better. The function should return 10 then and not 0.

The stuff I have written does work more or less, but its clearly not effective or elegant in any way. Also I assume this question does concern hundreds of people because every scientist has to format numbers in that way. So I'm sure there is a ready to use solution somewhere but I haven't found it yet. Probably my google skills aren't good enough but I wasn't able to find a solution to this in two days and now I ask here.

For testing my code I used this the following but more is needed.

errors = [0.2,1.123,1.0, 123123.1233215,0.123123123768]
values = [12.3453,123123321.4321432, 0.000321 ,321321.986123612361236,0.00001233214 ]

for value, error in zip(values, errors):
print "Teste Value: ",value, "Error:", error
print "Result: ", signigicant(value, error)
È stato utile?

Soluzione

import math

def round_on_error(value, error):
    significant_digits = 10**math.floor(math.log(error, 10))
    return value // significant_digits * significant_digits

Example:

>>> errors = [0.2,1.123,1.0, 123123.1233215,0.123123123768]
>>> values = [12.3453,123123321.4321432, 0.000321 ,321321.986123612361236,0.00001233214 ]
>>> map(round_on_error, values, errors)
[12.3, 123123321.0, 0.0, 300000.0, 0.0]

And if you want to keep a value that is inferior to its error

if (value <  error)
    return value
else
    def round_on_error(value, error):
    significant_digits = 10**math.floor(math.log(error, 10))
    return value // significant_digits * significant_digits
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top