0

Hopefully a simple one, I have a number, say 1234567.890 this number could be anything but will be this length.

How do I truncate the first 3 numbers so it turns into 4567.890?

This could be any number so subtracting 123000 will not work.


I'm working with map data in UTM coordinates (but that should not matter)

Example

x = 580992.528
y = 4275267.719

For x, I want 992.528

For y, I want 267.719

Note: y has an extra digit to the left of the decimal so 4 need removing

Troll
  • 1,895
  • 3
  • 15
  • 34
Spatial Digger
  • 1,883
  • 1
  • 19
  • 37
  • Do you need the trailing `0` at the end? – Freddy Mcloughlan Mar 12 '22 at 02:53
  • Why do you want to remove the first 3 digits? I get the impression that you may have limited the scope of your question to the task you are currently working on when there might in fact be a better solution with a slightly different approach to the larger problem. – Locke Mar 12 '22 at 02:55
  • @FreddyMcloughlan it's a placeholder – Spatial Digger Mar 12 '22 at 02:55
  • I'm working with coordinate data and the visualiser cannot handle UTM coordinates as they are too long, so I want to trim them from the front, view them, then add them back. Ah which means I need to record what gets trimmed... – Spatial Digger Mar 12 '22 at 02:58
  • @SpatialDigger you might find it helpful to try using https://docs.python.org/3/library/decimal.html. `Decimal` is oriented towards storing values which are far too large/long or require a high level of precision to store normally. Python would probably work fine if you substituted `Decimal` instances for the numbers, but it might give your visualizer some issues. You can apply an offset to all of your points and convert them back to regular numbers with `float(x)` for display. The important part is that it would ensure the splitting does not mess with the formatting/accuracy of the numbers. – Locke Mar 12 '22 at 03:10
  • This would be so much easier if it were about keeping everything up the the "thousands-digit" or if the number of digits before and after the dot were fixed. "First three digits" seems tricky, except for the obvious way via string. – Kelly Bundy Mar 12 '22 at 03:17
  • Post us a couple of examples of UTM coordinates, is it given they have six digits e.g. 18N 780950E 2052283N? – smci Mar 12 '22 at 03:23
  • Why should `1234567.890` become `4567.890` but `4275267.719` should become `267.719`? – Kelly Bundy Mar 12 '22 at 03:38

4 Answers4

3

You can use slices for this:

x = 1234567.890

# This is still a float
x = float(str(x)[3:])

print(x)

Outputs:

4567.89

As [3:] gets the starts the index at 3 and continues to the end of the string

Freddy Mcloughlan
  • 4,129
  • 1
  • 13
  • 29
2

Update after your edit

The simplest way is to use Decimal:

from decimal import Decimal

def fmod(v, m=1000, /):
    return float(Decimal(str(v)) % m)

print(fmod(x))
print(fmod(y))

Output

992.528
267.719

If you don't use string, you will have some problems with floating point in Python.

Demo:

n = 1234567.890
i = 0
while True:
    m = int(n // 10**i)
    if m < 1000:
        break
    i += 1
r = n % 10**i

Output:

>>> r
4567.889999999898

>>> round(r, 3)
4567.89

Same with Decimal from decimal module:

from decimal import Decimal

n = 1234567.890
n = Decimal(str(n))
i = 0
while True:
    m = int(n // 10**i)
    if m < 1000:
        break
    i += 1
r = n % 10**i

Output:

>>> r
Decimal('4567.89')

>>> float(r)
4567.89
Corralien
  • 109,409
  • 8
  • 28
  • 52
  • 1
    Slight variation: `r = n % 10**i` – Kelly Bundy Mar 12 '22 at 03:21
  • With `decimal`, I think you can use the `logb` method instead of your loop (not sure it's the best, didn't read it all). Then again, in that solution you're using string, in which case Freddy's continuation seems much simpler anyway :-) – Kelly Bundy Mar 12 '22 at 03:53
  • @KellyBundy. I used string just to show it's mandatory for this kind of problem due to the representation of floating point in python. My first solution doesn't use string and works except for the decimal part. – Corralien Mar 12 '22 at 07:31
0

This approach simply implements your idea.

  • int_len is the length of the integer part that we keep
  • sub is the rounded value that we will subtract the original float by

Code

Here is the code that implements your idea.

import math


def trim(n, digits):
    int_len = len(str(int(n))) - digits  # length of 4567
    sub = math.floor(n / 10 **int_len) * 10**int_len

    print(n - sub)

But as Kelly Bundy has pointed out, you can use modulo operation to avoid the complicated process of finding the subtrahend.

def trim(n, digits):
    int_len = len(str(int(n))) - digits  # length of 4567

    print(n % 10**int_len)

Output

The floating point thing is a bit cursed and you may want to take Corralien's answer as an alternative.

>>> n = 1234567.890

>>> trim(n, 3)
4567.889999999898
Troll
  • 1,895
  • 3
  • 15
  • 34
-2
def get_slice(number, split_n):
  return number - (number // 10**split_n) * 10**split_n
saganaga
  • 63
  • 7
  • 2
    Welcome to Stack Overflow. Code is a lot more helpful when it is accompanied by an explanation. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please [edit] your question and explain how it answers the specific question being asked. See [answer]. – ChrisGPT was on strike Mar 12 '22 at 12:20