how to convert from Decimal('1.23456789') to Decimal('1.234')

Discussion in 'Python' started by valpa, Mar 23, 2009.

  1. valpa

    valpa Guest

    I only need the 3 digits after '.'

    Is there any way other than converting from/to string?
     
    valpa, Mar 23, 2009
    #1
    1. Advertising

  2. valpa

    alex23 Guest

    On Mar 23, 4:40 pm, valpa <> wrote:
    > I only need the 3 digits after '.'
    >
    > Is there any way other than converting from/to string?


    I'm not sure if this is the canonical way but it works:

    >>> d = Decimal('1.23456789')
    >>> three_places = Decimal('0.001') # or anything that has the exponent depth you want
    >>> d.quantize(three_places, 'ROUND_DOWN')

    Decimal('1.234')
     
    alex23, Mar 23, 2009
    #2
    1. Advertising

  3. valpa

    Hyunchul Kim Guest

    In that case, I usually use

    # when rounding is proper,
    s = '1.23456789'
    print round(float(s))

    or

    # when cut out is proper,
    from math import floor
    print floor(float(s)*1000)/1000

    Hyunchul

    valpa wrote:
    > I only need the 3 digits after '.'
    >
    > Is there any way other than converting from/to string?
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >
    >
    >
     
    Hyunchul Kim, Mar 23, 2009
    #3
  4. On Sun, 22 Mar 2009 23:40:38 -0700, valpa wrote:

    > I only need the 3 digits after '.'
    >
    > Is there any way other than converting from/to string?


    You should Read the Fine Manual:

    http://docs.python.org/library/decimal.html


     
    Steven D'Aprano, Mar 23, 2009
    #4
  5. On Mar 23, 7:01 am, alex23 <> wrote:
    > On Mar 23, 4:40 pm, valpa <> wrote:
    >
    > > I only need the 3 digits after '.'

    >
    > > Is there any way other than converting from/to string?

    >
    > I'm not sure if this is the canonical way but it works:
    >
    > >>> d = Decimal('1.23456789')
    > >>> three_places = Decimal('0.001') # or anything that has the exponent depth you want
    > >>> d.quantize(three_places, 'ROUND_DOWN')

    >
    > Decimal('1.234')


    Yes, that's the official 'right way'. There's
    also a _rescale method that does this:

    >>> Decimal('1.23456789')._rescale(-3, 'ROUND_HALF_EVEN')

    Decimal('1.235')

    .... but as the leading underscore indicates, it's
    private and undocumented, so you shouldn't rely on it
    not to change or disappear in a future version.

    The two methods are subtly different, in that the
    quantize method respects the current context, while
    the _rescale method ignores it. For example:

    >>> getcontext().prec = 3
    >>> Decimal('1.23456789').quantize(Decimal('0.001'))

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/Users/dickinsm/python_source/trunk/Lib/decimal.py", line
    2364, in quantize
    'quantize result has too many digits for current context')
    File "/Users/dickinsm/python_source/trunk/Lib/decimal.py", line
    3735, in _raise_error
    raise error(explanation)
    decimal.InvalidOperation: quantize result has too many digits for
    current context
    >>> Decimal('1.23456789')._rescale(-3, 'ROUND_DOWN')

    Decimal('1.234')
    [61114 refs]

    Mark
     
    Mark Dickinson, Mar 23, 2009
    #5
  6. valpa

    Mensanator Guest

    On Mar 23, 2:24�am, Steven D'Aprano
    <> wrote:
    > On Sun, 22 Mar 2009 23:40:38 -0700, valpa wrote:
    > > I only need the 3 digits after '.'

    >
    > > Is there any way other than converting from/to string?

    >
    > You should Read the Fine Manual:
    >
    > http://docs.python.org/library/decimal.html
    >
    >
     
    Mensanator, Mar 23, 2009
    #6
  7. On Mar 23, 6:40 am, valpa <> wrote:
    > I only need the 3 digits after '.'
    >
    > Is there any way other than converting from/to string?


    And in Python 3.0, just use the built-in round function:

    >>> from decimal import Decimal
    >>> round(Decimal('1.23456789'), 3)

    Decimal('1.235')

    This uses the rounding specified by the context, so if
    you want a rounding mode other than the default
    ROUND_HALF_EVEN, just set the context rounding
    appropriately:

    >>> from decimal import getcontext, ROUND_DOWN
    >>> getcontext().rounding = ROUND_DOWN
    >>> round(Decimal('1.23456789'), 3)

    Decimal('1.234')

    Mark
     
    Mark Dickinson, Mar 23, 2009
    #7
  8. On Mon, 23 Mar 2009 01:45:53 -0700, Mensanator wrote:

    >> but you can create a helper
    >> function very easily:
    >>
    >> def round(dec, places, rounding=decimal.ROUND_HALF_UP): � � return
    >> dec.quantize(decimal.Decimal(str(10**-places)), rounding)

    >
    > Still ugly. I would do this:
    >
    >>>> a = Decimal('1.23456789')

    >
    >>>> for i in xrange(1,6):

    > print Context.create_decimal(Context(i,ROUND_DOWN),a)


    Well, that's hardly any less ugly.

    And it also gives different results to my function: my function rounds to
    <places> decimal places, yours to <i> digits. Very different things.


    --
    Steven
     
    Steven D'Aprano, Mar 23, 2009
    #8
  9. valpa

    Mensanator Guest

    On Mar 23, 5:48 am, Steven D'Aprano <st...@REMOVE-THIS-
    cybersource.com.au> wrote:
    > On Mon, 23 Mar 2009 01:45:53 -0700, Mensanator wrote:
    > >> but you can create a helper
    > >> function very easily:

    >
    > >> def round(dec, places, rounding=decimal.ROUND_HALF_UP): return
    > >> dec.quantize(decimal.Decimal(str(10**-places)), rounding)

    >
    > > Still ugly. I would do this:

    >
    > >>>> a = Decimal('1.23456789')

    >
    > >>>> for i in xrange(1,6):

    > >    print Context.create_decimal(Context(i,ROUND_DOWN),a)

    >
    > Well, that's hardly any less ugly.


    I wouldn't say so since there are no strings attached. Didn't the
    OP specifically ask for a solution that didn't involve strings?

    >
    > And it also gives different results to my function: my function rounds to
    > <places> decimal places, yours to <i> digits. Very different things.


    Yeah, I know all about that. I work in Environmental Remediation.
    That's real science, where rounding to decimal places is strictly
    forbidden, significant digits must be preserved. That means rounding
    to digits. Do you know what kind of hoops I have to jump through to
    get Access or Excel to round properly when doing unit conversion?

    Surely you're not so maive that you think dividing by 1000 simply
    moves
    the decimal point three places?

    >
    > --
    > Steven
     
    Mensanator, Mar 23, 2009
    #9
  10. On Mon, 23 Mar 2009 10:06:23 -0700, Mensanator wrote:

    > On Mar 23, 5:48 am, Steven D'Aprano <st...@REMOVE-THIS-
    > cybersource.com.au> wrote:
    >> On Mon, 23 Mar 2009 01:45:53 -0700, Mensanator wrote:
    >> >> but you can create a helper
    >> >> function very easily:

    >>
    >> >> def round(dec, places, rounding=decimal.ROUND_HALF_UP): return
    >> >> dec.quantize(decimal.Decimal(str(10**-places)), rounding)

    >>
    >> > Still ugly. I would do this:

    >>
    >> >>>> a = Decimal('1.23456789')

    >>
    >> >>>> for i in xrange(1,6):
    >> >    print Context.create_decimal(Context(i,ROUND_DOWN),a)

    >>
    >> Well, that's hardly any less ugly.

    >
    > I wouldn't say so since there are no strings attached. Didn't the OP
    > specifically ask for a solution that didn't involve strings?


    No, the OP asked for a solution that didn't involve converting the
    decimal number to a string first.

    Besides, I don't believe you can specify the rounding mode unless you use
    strings *wink*

    >>> type(ROUND_DOWN)

    <type 'str'>



    >> And it also gives different results to my function: my function rounds
    >> to <places> decimal places, yours to <i> digits. Very different things.

    >
    > Yeah, I know all about that. I work in Environmental Remediation. That's
    > real science, where rounding to decimal places is strictly forbidden,
    > significant digits must be preserved. That means rounding to digits.


    Okay, so in other words you solved your problem rather than the OP's
    problem.


    > Do
    > you know what kind of hoops I have to jump through to get Access or
    > Excel to round properly when doing unit conversion?


    I feel your pain.


    > Surely you're not so maive that you think dividing by 1000 simply moves
    > the decimal point three places?


    Of course it does, if you're using real numbers. If you're using floats,
    no, not quite, there are rounding issues involved, and underflow.

    I'm not sure why you raise this. Is this a general rant, or do you have a
    specific criticism?


    --
    Steven
     
    Steven D'Aprano, Mar 23, 2009
    #10
  11. valpa

    Mensanator Guest

    On Mar 23, 5:42 pm, Steven D'Aprano <st...@REMOVE-THIS-
    cybersource.com.au> wrote:
    > On Mon, 23 Mar 2009 10:06:23 -0700, Mensanator wrote:
    > > On Mar 23, 5:48 am, Steven D'Aprano <st...@REMOVE-THIS-
    > > cybersource.com.au> wrote:
    > >> On Mon, 23 Mar 2009 01:45:53 -0700, Mensanator wrote:
    > >> >> but you can create a helper
    > >> >> function very easily:

    >
    > >> >> def round(dec, places, rounding=decimal.ROUND_HALF_UP): return
    > >> >> dec.quantize(decimal.Decimal(str(10**-places)), rounding)

    >
    > >> > Still ugly. I would do this:

    >
    > >> >>>> a = Decimal('1.23456789')

    >
    > >> >>>> for i in xrange(1,6):
    > >> >    print Context.create_decimal(Context(i,ROUND_DOWN),a)

    >
    > >> Well, that's hardly any less ugly.

    >
    > > I wouldn't say so since there are no strings attached. Didn't the OP
    > > specifically ask for a solution that didn't involve strings?

    >
    > No, the OP asked for a solution that didn't involve converting the
    > decimal number to a string first.
    >
    > Besides, I don't believe you can specify the rounding mode unless you use
    > strings *wink*
    >
    > >>> type(ROUND_DOWN)

    >
    > <type 'str'>
    >
    > >> And it also gives different results to my function: my function rounds
    > >> to <places> decimal places, yours to <i> digits. Very different things..

    >
    > > Yeah, I know all about that. I work in Environmental Remediation. That's
    > > real science, where rounding to decimal places is strictly forbidden,
    > > significant digits must be preserved. That means rounding to digits.

    >
    > Okay, so in other words you solved your problem rather than the OP's
    > problem.


    People other than the OP read these threads. Do you want to
    give people the impression that quantize is the only option?

    >
    > > Do
    > > you know what kind of hoops I have to jump through to get Access or
    > > Excel to round properly when doing unit conversion?

    >
    > I feel your pain.


    So surely you don't want to give the impression that
    all Decimal is good for is emulating Excel?

    >
    > > Surely you're not so maive that you think dividing by 1000 simply moves
    > > the decimal point three places?

    >
    > Of course it does, if you're using real numbers.


    Computers have real numbers?

    > If you're using floats,
    > no, not quite, there are rounding issues involved, and underflow.


    And that's why we have Decimal, right?

    >
    > I'm not sure why you raise this. Is this a general rant, or do you have a
    > specific criticism?


    At first, I could not understand the need for nor the syntax of
    quantize. It seemed very clunky having to specify a template and
    a rounding, especially since it also accepts a Context object.

    And upon seeing Context.create_decimal, I thought "why would
    I ever use quantize when I can do it the 'right' way?"

    But that was when I first saw it, so the rant isn't about
    which way to do something, but pointing out there may be
    other solutions that are more appropriate to the problem.

    Speaking of doing things the 'right' way, I seem to have
    blundered my way into the answer I was looking for. According
    to the documention

    <quote>
    create_decimal(num)
    Creates a new Decimal instance from num but using self as context.
    Unlike the Decimal constructor, the context precision, rounding
    method, flags, and traps are applied to the conversion.
    </quote>

    and that's exactly what I want. I may have one context for
    calculation and another for printing, so I want to be able
    to programatically impose my printing context on a number
    without affecting it.

    Of course it didn't work.

    >>> Context.create_decimal('1.234456789')


    Traceback (most recent call last):
    File "<pyshell#13>", line 1, in <module>
    Context.create_decimal('1.234456789')
    TypeError: unbound method create_decimal() must be called with Context
    instance as first argument (got str instance instead)

    Ok, the Traceback says I need a Context instance, so I tried
    >>> Context.create_decimal(Context(4),'1.234456789')

    Decimal('1.234')

    So I thought ok, but what's this self referred to in the docs
    and why does it say "create_decimal(num)" if I have to have a
    Context instance as the first parameter?

    But wait, the Traceback also says "unbound method". Was I supposed
    to have parentheses after Context?
    >>> Context().create_decimal('1.234456789')

    Decimal('1.234456789')

    Duh.

    The self must refer to the default Context that's in place.
    Providing I use the bound method.

    If I had done it the right way from the start I would have gotten
    a precision of 28 (unless I mucked around with the default Context)
    and probably would never have figured out that with an unbound
    method I could impose a Context on a number on the fly.

    Man, that's subtle.

    >
    > --
    > Steven
     
    Mensanator, Mar 24, 2009
    #11
  12. On Mon, 23 Mar 2009 17:19:48 -0700, Mensanator wrote:

    >> >> And it also gives different results to my function: my function
    >> >> rounds to <places> decimal places, yours to <i> digits. Very
    >> >> different things.

    >>
    >> > Yeah, I know all about that. I work in Environmental Remediation.
    >> > That's real science, where rounding to decimal places is strictly
    >> > forbidden, significant digits must be preserved. That means rounding
    >> > to digits.

    >>
    >> Okay, so in other words you solved your problem rather than the OP's
    >> problem.

    >
    > People other than the OP read these threads. Do you want to give people
    > the impression that quantize is the only option?


    The only option for what? Solving the OP's problem, or your problem, or
    some other problem? How many different problems are we going to solve in
    this thread?

    At the very least, when taking a detour to solve a different problem, say
    so, and point out why your problem is a more interesting/useful problem
    to solve.


    >> > Do
    >> > you know what kind of hoops I have to jump through to get Access or
    >> > Excel to round properly when doing unit conversion?

    >>
    >> I feel your pain.

    >
    > So surely you don't want to give the impression that all Decimal is good
    > for is emulating Excel?


    That's a non sequitor. It does not follow that just because I sympathize
    with your difficulties with Excel, that I therefore want to give the
    impression that Decimal is only good for emulating Excel.


    >> > Surely you're not so maive that you think dividing by 1000 simply
    >> > moves the decimal point three places?

    >>
    >> Of course it does, if you're using real numbers.

    >
    > Computers have real numbers?


    You don't have to use computers to divide by 1000. As difficult as it is
    to believe, throughout history people have done mathematical calculations
    without the use of computing devices.


    >> If you're using floats,
    >> no, not quite, there are rounding issues involved, and underflow.

    >
    > And that's why we have Decimal, right?


    I'm sure that the Decimal standard wasn't invented just so people can
    divide by 1000.



    --
    Steven
     
    Steven D'Aprano, Mar 24, 2009
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vitaliy
    Replies:
    1
    Views:
    502
    Peter Otten
    May 29, 2008
  2. Daniel Moore
    Replies:
    19
    Views:
    346
  3. pembed2003

    Regex to format 1234 to 1,234

    pembed2003, Apr 27, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    161
    Lukas Mai
    Apr 28, 2004
  4. Jason Stacy
    Replies:
    2
    Views:
    152
    Jürgen Exner
    May 5, 2008
  5. Quarco

    ereg: ? 1234.56 ==> ? 1.234,56

    Quarco, Feb 9, 2005, in forum: Javascript
    Replies:
    3
    Views:
    178
    Quarco
    Feb 10, 2005
Loading...

Share This Page