Initialising attotimedelta with 0.1 seconds
Hi,
Thanks for writing the package. I’m looking to use it in my geophysical data processing package (resistics, resistics.io), which I’m currently re-writing. I read the doc info about attotimedelta, which states:
All arguments are optional and default to 0. All arguments may be ints, longs, or floats, and may be positive or negative.
I’ve been using attotimedelta(seconds=1/4096) and this appears to work well:
>>> from attotime import attotimedelta
>>> attotimedelta(seconds=1/4096)
attotime.objects.attotimedelta(0, 0, 244, 140.625)
However, if I try doing something similar with seconds=0.1, I appear to get some trailing numbers
>>> attotimedelta(seconds=0.1)
attotime.objects.attotimedelta(0, 0, 100000, 0.0000000055511151231)
>>> attotimedelta(seconds=0.1, microseconds=0, nanoseconds=0)
attotime.objects.attotimedelta(0, 0, 100000, 0.0000000055511151231)
Finally, trying:
>>> attotimedelta(microseconds=100_000)
attotime.objects.attotimedelta(0, 0, 100000)
I just wanted to double check whether attotimedelta should be able to resolve seconds=0.1 or if I am using it incorrectly?
Thanks
Comments (4)
-
reporter -
repo owner - changed status to wontfix
You correctly identified what is happening. There are a couple of workarounds you may consider:
First, you could give it Decimals built from strings as indicated in the Stack Overflow post:
>>> attotimedelta(seconds=Decimal("0.1")) attotime.objects.attotimedelta(0, 0, 100000)
It also behaves correctly if given strings:
>>> attotimedelta(seconds="0.1") attotime.objects.attotimedelta(0, 0, 100000)
Alternatively, you can modify the precision to the level necessary for your use case, but keep in mind the handling of repeated reductions to microseconds may still mean you do not get the ultimate precision you are looking for:
>>> from decimal import localcontext >>> with localcontext() as context: ... context.prec = 35 ... attotimedelta(seconds=0.1) ... attotime.objects.attotimedelta(0, 0, 100000, 0.0000000055511151231257827) attotime.objects.attotimedelta(0, 0, 100000, 0.00000000555111512312578270211815834) >>> with localcontext() as context: ... context.prec = 100 ... attotimedelta(seconds=0.1)
There may be some improvements to be made by reducing the number of sequential reductions made (or by clever casting to strings?), but I am not currently pursuing it.
The documentation should be made clearer to indicate Decimal objects are a supported input type.
-
reporter Hi, thanks for the response. I ended up changing how I construct the attotimedelta, adding some logic to ensure I only pass floats to nanoseconds and otherwise, pass integers where possible to seconds and microseconds.
Cheers
-
repo owner 0.3.0 (commit c23face) adds some explicit type checking to hopefully make this a little clearer in the future.
- Log in to comment
Looking through the code and reading a bit more, it appears as though this has to do with floating point arithmetic
Using "Decimal" in Python - Stack Overflow