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

2009-03-24 Thread Steven D'Aprano
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
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread valpa
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


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

2009-03-23 Thread alex23
On Mar 23, 4:40 pm, valpa valpass...@gmail.com 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')
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Hyunchul Kim

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


  


--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Steven D'Aprano
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


[quote]
The quantize() method rounds a number to a fixed exponent. This method is 
useful for monetary applications that often round results to a fixed 
number of places:

 Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
 Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')

[end quote]

In my opinion, that's hideously ugly, 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)



-- 
Steven
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Mark Dickinson
On Mar 23, 7:01 am, alex23 wuwe...@gmail.com wrote:
 On Mar 23, 4:40 pm, valpa valpass...@gmail.com 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
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Mark Dickinson
On Mar 23, 6:40 am, valpa valpass...@gmail.com 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
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Mensanator
On Mar 23, 2:24�am, Steven D'Aprano
ste...@remove.this.cybersource.com.au 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

 [quote]
 The quantize() method rounds a number to a fixed exponent. This method is
 useful for monetary applications that often round results to a fixed
 number of places:

  Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
 Decimal('7.32')
  Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)

 Decimal('8')

 [end quote]

 In my opinion, that's hideously ugly,

In looking at this for the first time, it struck
me as funny why the first argument to quantize
even requires a number since you can pass a
Conext as an argument. But if you do, precision
is ignored. Quantize isn't the way to do that.

 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)
1
1.2
1.23
1.234
1.2345

 print a
1.23456789



 --
 Steven

--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Steven D'Aprano
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
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Mensanator
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

--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Steven D'Aprano
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
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-03-23 Thread Mensanator
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

--
http://mail.python.org/mailman/listinfo/python-list