Forum Moderators: Staff
Poser Python Scripting F.A.Q (Last Updated: 2024 Sep 18 2:50 am)
I'm not sure I understand the problem. If your application is to print version numbers, why represent them as floats, at all?
In general, to represent a number as a string rounded to a certain number of decimal places, say 3, you can use ("%.3f" % x)
.
for i in numpy.arange( 0.1, 0.9, 0.1 ):
print("%.1f" % i)
-- I'm not mad at you, just Westphalian.
We could literally answer your questions about goofy floats but first let's decide if that rabbit hole is worth ANY of the grief. I suggest instead that you deal with version strings using the dedicated, properly designed features of Python for this. Have a look.
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)
Oh crap. Right after I wrote that I discovered you have to install that "packaging" package and you might not be able to in Poser Python.
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)
OK so after a quick experiment I conclude your problem is simply that adding .1 each time is a bad way to do as the slight inaccuracy of representing .1 accumulates. Instead, just iterate on an integer and divide by 10.
Example:
for i in range(100):
name = 'foo_copy_' + str(i/10) + '.bar'
print(name)
Works just fine
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)
Honestly, though, I don't know why you need 0.1, 0.2, 0.3 ... instead of just 1, 2, 3 ...
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)
I cleaned up your function - it can be much simpler.
# make a new ( numbered ) copy of the original file
def uniquify( path, ext ):
file_name = path + ext
i = 0
while isfile(file_name):
i += 1
file_name = path + "_copy_" + str(i/10) + ext
return file_name
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)
bagginsbill posted at 8:28AM Tue, 24 August 2021 - #4425960
I cleaned up your function - it can be much simpler.
# make a new ( numbered ) copy of the original file def uniquify( path, ext ): file_name = path + ext i = 0 while isfile(file_name): i += 1 file_name = path + "_copy_" + str(i/10) + ext return file_name
To make that work with Poser Versions != 12, you have to execute this first:
from __future__ import division
If you don't you will get garbage with this function.
But, as @odf said: The better way is to use Pythons format functions to convert numbers to strings.
Python 3 (Poser 12) understands the old way of formatting strings with "%", and Python 2 (P11) can handle ".format(...)" strings preferred with Python 3.
I'm not using Python 12 - but I am using Python 3 because 2 is dead.
Anyway - yes if you're in Python 2 (Poser 11 or below) then division by 10 needs to be i / 10.0.
And yes you can format umpteen ways
f'{i / 10:.1f}'
'%.1f' % (i / 10.0)
str(i / 10.0)
You pick which way you're comfortable with. I usually pick based on the simplest syntax, or the shortest amount of coding, which generally means fewer mistakes.
Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)
As far as I know, the forum is called "Python" and not "Python 3".
By the way, in the Poser universe there are significantly more Poser 11 users who need Python 2 than those who use Poser 12 with Python 3. And that's likely to continue for a while. As I see it, P12 will probably need another 3-5 years to become reasonably stable and usable. Which means Python 2 will continue to exist in the Poser universe....
Using Python standards (like format for displaying numbers) also has the advantage that there are less problems with conversions/changes. The current disaster regarding Python 3 incompatibility of most scripts should be incentive enough to do things differently in the future and stick to established standards.
adp001 posted at 6:36PM Tue, 24 August 2021 - #4425963
bagginsbill posted at 8:28AM Tue, 24 August 2021 - #4425960
I cleaned up your function - it can be much simpler.
# make a new ( numbered ) copy of the original file def uniquify( path, ext ): file_name = path + ext i = 0 while isfile(file_name): i += 1 file_name = path + "_copy_" + str(i/10) + ext return file_name
To make that work with Poser Versions != 12, you have to execute this first:
from __future__ import division
If you don't you will get garbage with this function.
My preference is to use str(i / 10.0)
which will work correctly in both Python 2 and 3. Similarly, I like to use the //
in Python 2 because it won't break when one upgrades to 3.
-- I'm not mad at you, just Westphalian.
adp001 posted at 6:42PM Tue, 24 August 2021 - #4426000
https://docs.python.org/2.7/library/decimal.html
:) :) :)
I didn't say that Python 2 didn't have it. It's just that the Python 3 manual was the first hit I found and I was too lazy to check if it was also available for Python 2.
-- I'm not mad at you, just Westphalian.
odf posted at 6:43PM Tue, 24 August 2021 - #4426001
My preference is to use
str(i / 10.0)
which will work correctly in both Python 2 and 3. Similarly, I like to use the//
in Python 2 because it won't break when one upgrades to 3.
Yup, mine too. But it still makes more sense to write a formatted string like ... + "%1.1f" % [value] + ...
Thanks for your feedback guys.
I have no intention of using flouting points in the example cited. I am actually using integers for that. However while writing the code for this I became curious as to how best to work with floating points. (I also tried the decimal module.)
I appreciate your responses.
p.s. @BagginsBill... Thanks for the tidy up
Locked Out
This site uses cookies to deliver the best experience. Our own cookies make user accounts and other features possible. Third-party cookies are used to display relevant ads and to analyze how Renderosity is used. By using our site, you acknowledge that you have read and understood our Terms of Service, including our Cookie Policy and our Privacy Policy.
so using the following code I came across the "can't represent this decimal properly" feature.
I understand the reasoning for this, it has to do with the fact that decimals cannot be accurately represented by binary.
But lets say I need real precision ( for some engineering venture perhaps ). The results in blue are what I want, the results in red are what I am getting.
Is there a workaround in python to actually return the decimals I want?
changing the .1 to 1/10 yields the same result
similarly the following code returns odd numbers also.
which returns
if I round the result:
python returns the following ...
EDIT : a temporary workaround seems to be slicing the returned number like this
Locked Out