question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

uint64 converted silently to float64 when adding an int

See original GitHub issue

This code

import numpy
a = numpy.zeros(1, dtype = numpy.uint64)[0]
print(type(a))
i = 1
print(type(i))
a += i
print(type(a))

prints

<class 'numpy.uint64'>
<class 'int'>
<class 'numpy.float64'>

which was a big surprise for me. Why would adding an integer to uint64 result in a floating point value?

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:12
  • Comments:22 (12 by maintainers)

github_iconTop GitHub Comments

4reactions
bergkvistcommented, May 26, 2020

Might be a bit of a radical suggestion, but what about dropping support for uint64 alltogether? Who needs whole numbers between 2**63 and 2**64 anyways?

This would mean that accumulative type inflation of integers would converge to int64 instead of float64. Information would not be lost silently (nor would there be need for an error)

2reactions
seibertcommented, Aug 20, 2019

Fast forward a few years from the last comment on this issue, and I’m curious if there is now any interest from the NumPy core developers in considering a change to the overall type casting behavior of uint64 + int64 => float64.

Fundamentally, there are two differently problematic approaches to deal with typing a fixed maximum integer size (assuming you don’t want to deal with value-dependent typing):

  1. Accept potential overflow when adding uint64 to int64 by making the result int64.
  2. Accept potential loss of precision when adding uint64 to int64 by making the result float64.

Option 2 is what NumPy does (and implicitly Javascript, which doesn’t distinguish between ints and floats with its Number type) and Option 1 is what C, C++ and many other languages do. (It is unfortunate that signed overflow is undefined in C, but it is well-defined in many other languages, like Java, Rust and Julia.)

Beyond Option 1 being more intuitive for anyone familiar with integer arithmetic in other languages, I think the fact that NumPy no longer accepts floats as array indices (with good reason!) makes Option 2 even more problematic as users can accidentally compute a float index when combining two integer indices. This problem also pops up in Numba (where we attempt to mimic NumPy casting rules), making it unwise for us to use unsigned ints for things like ranges because they will accidentally create floats when combined with other integer values and cause compilation errors. Other efforts to compile user code written against the NumPy API will also face this question.

Additionally, the current approach seems kind of ad-hoc and inconsistent, given that the far more common int64 + int64 has a similar overflow issue, yet this case is not cast into a float64.

Given how long this behavior has been in place, it may be impractical to change, but if it were in principle possible, would people be in favor of uint64 + int64 => int64?

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to change a float64 number to uint64 in a right way?
The problem is not with the conversion but that the number is too large an integer to be stored exactly as a float64...
Read more >
Cannot use -a (type int) as type float64 in function argument
Hi everyone, I'm getting this error: Cannot use -a (type int) as type float64 in function argument. Code: package main import (
Read more >
Survey of Rounding Implementations in Go - Cockroach Labs
The conversion of v (a float64) to uint64 is not well defined and works differently on amd64 and arm. While fixing the arm...
Read more >
pandas: Cast DataFrame to a specific dtype with astype()
uint64, u8, 64-bit unsigned integer. float16, f2, 16-bit floating-point number. float32, f4, 32-bit floating-point number. float64, f8 ...
Read more >
Integers and Floating-Point Numbers - Julia Documentation
For example, 1 is an integer literal, while 1.0 is a floating-point ... Int Int32 julia> UInt UInt32 # 64-bit system: julia> Int...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found