# Why does scientific notation break the range function?

**URL:** <https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014>\
**Category:** New to Julia\
**Created:** [April 25, 2022, 8:46pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014 "2022-04-25T20:46:57Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 26, 2022, 4:24pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/44 "2022-04-26T16:24:41Z")

</div>

> [@chadagreene](#):
>
> No, it’s terrible!

So, good, but not stellar? 😉

But, replace `Union{}` with `Integer`, and I don’t really see how to improve it further. Maybe you have a suggestion?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 26, 2022, 4:26pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/45 "2022-04-26T16:26:43Z")

</div>

> [@nilshg](#):
>
> ```julia
> A type union is an abstract type which includes all instances of any of its argument types. The empty union Union{} is the bottom type of Julia.
> 
> ```

oh, lets be open minded here with the people just arriving to the language… There is a lot _technical_ information in that phrase. Understanding that occurs not at the same point in Julia programming than when doing some scripts to analyze data series and plots.

(myself included, I barely understand what the “The empty union … is the bottom type of Julia” means, I remember hearing something about it from a presentation at JuliaCon about the type system and now can sort of reason about it, but I’m far to really being able to explain that)

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 26, 2022, 4:29pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/46 "2022-04-26T16:29:43Z")

</div>

> [@lmiq](#):
>
> There is a lot _technical_ information in that phrase. Understanding that occurs not at the same point in Julia programming than when doing some scripts to analyze data series and plots.

FWIW, Racket has [language levels](https://docs.racket-lang.org/drracket/htdp-langs.html).

---

<div class="post-metadata">

**Author:** ![chadagreene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chadagreene/32/34924_2.png) [@chadagreene](https://discourse.julialang.org/u/chadagreene)\
**Post date:** [April 26, 2022, 4:43pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/47 "2022-04-26T16:43:52Z")

</div>

> [@DNF](#):
>
> I don’t really see how to improve it further. Maybe you have a suggestion?

I’d start by identifying that the error occurs in the `range` function, because that’s the first thing people will want to know (yet it doesn’t appear anywhere in the current error message). Then I’d zero in on exactly where the error is within the `range` function, say what caused it, and conclude with some constructive advice on possible ways to fix the error.

That’s the order that people will want to process the information, and it’s the order the information should be presented in. I’d also write it in human language (a sentence) rather than a series of cryptic sentence fragments. Here’s my suggested rewrite:

```julia
ERROR in range(): Keyword argument length was entered as type Float64, but must be of type Integer.

```

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 26, 2022, 4:48pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/48 "2022-04-26T16:48:05Z")

</div>

> [@chadagreene](#):
>
> I’d start by identifying that the error occurs in the `range` function, because that’s the first thing people will want to know (yet it doesn’t appear anywhere in the current error message).

I believe this is a slight misconception: the problematic part in stack traces is in most cases the uppermost caller and not the lowermost callee.

---

<div class="post-metadata">

**Author:** ![chadagreene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chadagreene/32/34924_2.png) [@chadagreene](https://discourse.julialang.org/u/chadagreene)\
**Post date:** [April 26, 2022, 4:52pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/49 "2022-04-26T16:52:44Z")

</div>

> [@goerch](#):
>
> the problematic part in stack traces is in most cases the uppermost caller and not the lowermost callee.

What? Where in this Stacktrace does it say the error is in the `range` function?

```julia
Stacktrace:
  [1] top-level scope
    @ ~/Documents/coursework/Untitled-1.ipynb:1
  [2] eval
    @ ./boot.jl:373 [inlined]
  [3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base ./loading.jl:1196
  [4] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
  [5] invokelatest
    @ ./essentials.jl:714 [inlined]
  [6] (::VSCodeServer.var"#164#165"{VSCodeServer.NotebookRunCellArguments, String})()
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/serve_notebook.jl:19
  [7] withpath(f::VSCodeServer.var"#164#165"{VSCodeServer.NotebookRunCellArguments, String}, path::String)
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/repl.jl:184
  [8] notebook_runcell_request(conn::VSCodeServer.JSONRPC.JSONRPCEndpoint{Base.PipeEndpoint, Base.PipeEndpoint}, params::VSCodeServer.NotebookRunCellArguments)
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/serve_notebook.jl:13
  [9] dispatch_msg(x::VSCodeServer.JSONRPC.JSONRPCEndpoint{Base.PipeEndpoint, Base.PipeEndpoint}, dispatcher::VSCodeServer.JSONRPC.MsgDispatcher, msg::Dict{String, Any})
    @ VSCodeServer.JSONRPC ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/JSONRPC/src/typed.jl:67
 [10] serve_notebook(pipename::String, outputchannel_logger::Base.CoreLogging.SimpleLogger; crashreporting_pipename::String)
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/serve_notebook.jl:136
 [11] top-level scope
    @ ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/notebook/notebook.jl:32
 [12] include(mod::Module, _path::String)
    @ Base ./Base.jl:418
 [13] exec_options(opts::Base.JLOptions)
    @ Base ./client.jl:292
 [14] _start()
    @ Base ./client.jl:495

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 26, 2022, 4:58pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/50 "2022-04-26T16:58:20Z")

</div>

That part will be improved by [Why does scientific notation break the range function? - #25 by pfitzseb](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/25), but it looks like even with that change it’s missing the entry for the `logrange` function itself.

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 26, 2022, 4:59pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/51 "2022-04-26T16:59:07Z")

</div>

The MWE

```julia
function test(start, stop, length)
    range(start, stop, length=length)
end    

test(1, 2, 0.42)

```

yields

```julia
ERROR: TypeError: in keyword argument length, expected Union{Nothing, Integer}, got a value of type Float64
Stacktrace:
 [1] test(start::Int64, stop::Int64, length::Float64)
   @ Main 1.jl:2
 [2] top-level scope
   @ 1.jl:6

```

and yes you are right: the reference to `range` is missing…

But I would still search the problem either on top-level or in `test`…

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 26, 2022, 5:09pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/52 "2022-04-26T17:09:01Z")

</div>

> [@chadagreene](#):
>
> Where in this Stacktrace does it say the error is in the `range` function?

Whaaa? How on earth is `range` missing from the trace? I didn’t even notice that.

Anyone know why that happens?

---

<div class="post-metadata">

**Author:** ![trahflow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/trahflow/32/30585_2.png) [@trahflow](https://discourse.julialang.org/u/trahflow)\
**Post date:** [April 26, 2022, 5:19pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/53 "2022-04-26T17:19:13Z")

</div>

Well I guess the error is not _in_ the range function so it makes sense that it’s not part of the stack trace.  
Nevertheless, it would be nice if the error message would mention `range`.

A note on some [relevant part of the julia documentation](https://docs.julialang.org/en/v1/manual/methods/#Note-on-Optional-and-keyword-Arguments). It says

> Keyword arguments behave quite differently from ordinary positional arguments. In particular, they do not participate in method dispatch. Methods are dispatched based only on positional arguments, with keyword arguments processed after the matching method is identified.

I think this part could be a bit more specific, i.e. it could mention _how_ keyword arguments are processed after the matching method is identified. The way I understand it, type annotations on keyword arguments are just type assertions.

If above understanding is correct, the type assertion is probably a generic error message in base julia, which likely could easily be modified to print out the method that was identified in the preceding dispatch.

---

<div class="post-metadata">

**Author:** ![trahflow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/trahflow/32/30585_2.png) [@trahflow](https://discourse.julialang.org/u/trahflow)\
**Post date:** [April 26, 2022, 5:41pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/54 "2022-04-26T17:41:19Z")

</div>

Relevant issue: [better error for passing wrong type of keyword argument · Issue #29829 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/29829)  
Seems like the function/method name used to be part of the error message, but was changed. According to a comment by Jeff on the linked issue this _should_ be part of the stack trace.  
I’m confused now 😅

Edit:  
[here](https://github.com/JuliaLang/julia/blob/master/base/errorshow.jl#L62-L84) is how the error message is formed. It has a special case for `TypeError`s from keyword arguments. This is a bit weird, but I guess there was a deeper reason for that related to above issue.

---

<div class="post-metadata">

**Author:** ![suavesito](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/suavesito/32/34386_2.png) [@suavesito](https://discourse.julialang.org/u/suavesito)\
**Post date:** [April 26, 2022, 5:55pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/55 "2022-04-26T17:55:15Z")

</div>

> [@jules](#):
>
> For example when doing divisions with divisors that are not powers of two.

If all the operations done (`+`, `-`, `*`, `/`, `div`) use elements inside the set of possible integers representable by a `Float{16|32|64}` (or a multiple of an integer with a factor of 2^{-x} with x less than the size of the mantissa) _and_ the result of the operations is ~~always~~ in the end an integer, then you will get a (floating point) exact integer at the end.

But if you do something like `(a / 3.0) * 6.0` with `a` not divisible by 3, then what you describe could happen.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 26, 2022, 6:22pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/56 "2022-04-26T18:22:36Z")

</div>

> [@suavesito](#):
>
> But if you do something like `(a / 3.0) * 6.0` with `a` not divisible by 3 33 , then what you describe could happen.

Note: That wouldn’t give exact results with integer arithmetic (via `(a ÷ 3) * 6`) either.  
Basically, any calculation that you could do purely with `Integer` quantities is also exact with floating-point arithmetic, up to the maximum exactly representable consecutive integer.

More generally, the key rule to remember is that elementary operations (`+,-,*,/`) in floating-point arithmetic behave as _if_ they were computed exactly in infinite precision and then rounded to the closest representable floating-point value. So you only run into rounding errors when you have results (including intermediate results and inputs, of course) that are not exactly representable, like `0.1` or `2/3` or `exp(3.0)`. This doesn’t happen with integer values up to `maxintfloat`.

Floating-point rounding can sometimes be difficult to analyze, but it’s important not to over-mystify it. It’s a common misconception that things like `1.0 + 1.0` will somehow give `2.0 ± ϵ` in floating point.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [April 26, 2022, 6:29pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/57 "2022-04-26T18:29:18Z")

</div>

> [@stevengj](#):
>
> It’s a common misconception that things like `1.0 + 1.0` will somehow give `2.0 ± ϵ` in floating point.

Yes that was more or less my heuristic working with floats, don’t rely on exact results. I should read a bit more about the mechanics, I’m not doing numerical work so the lowest level didn’t matter much to me. But I clearly had a few of the misconceptions you mentioned here, so thanks for clarifying.

---

<div class="post-metadata">

**Author:** ![Volker\_Weissmann](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Volker\_Weissmann](https://discourse.julialang.org/u/Volker_Weissmann)\
**Post date:** [April 26, 2022, 7:54pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/58 "2022-04-26T19:54:26Z")

</div>

```julia
[1] top-level scope
    @ ~/Documents/coursework/Untitled-1.ipynb:1

```

First line in the jupyter notebook is `range(0,10, length=1e3)`.

---

<div class="post-metadata">

**Author:** ![Volker\_Weissmann](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Volker\_Weissmann](https://discourse.julialang.org/u/Volker_Weissmann)\
**Post date:** [April 26, 2022, 7:56pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/59 "2022-04-26T19:56:26Z")

</div>

> [@goerch](#):
>
> I believe this is a slight misconception: the problematic part in stack traces is in most cases the uppermost caller and not the lowermost callee.

The uppermost caller is usually something like the main() function.

---

<div class="post-metadata">

**Author:** ![chadagreene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chadagreene/32/34924_2.png) [@chadagreene](https://discourse.julialang.org/u/chadagreene)\
**Post date:** [April 26, 2022, 8:47pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/60 "2022-04-26T20:47:46Z")

</div>

That’s incorrect:

1. Notebook lines are not numbered (at least in my VS Code).

2. The first line of the notebook is NOT where the `range` call occurs. A Notebook cell containing this passage produces the same stacktrace message:

```julia
#this is a comment
5+5
x = range(0,10,length=1e3)

```

1. Sometimes a line of code may contain calls to more than one function. In such cases, it would be helpful to know that the error occurs in the call to the `range()` function. Therefore, I suggest that this would be a much, much more helpful error message than the current one:

```julia
ERROR in range(): Keyword argument length was entered as type Float64, but must be of type Integer.

```

---

<div class="post-metadata">

**Author:** ![Volker\_Weissmann](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Volker\_Weissmann](https://discourse.julialang.org/u/Volker_Weissmann)\
**Post date:** [April 26, 2022, 8:52pm UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/61 "2022-04-26T20:52:36Z")

</div>

> [@chadagreene](#):
>
> The first line of the notebook is NOT where the `range` call occurs. A Notebook cell containing this passage produces the same stacktrace message:

Ok, then that’s a real issue.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [April 27, 2022, 12:32am UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/62 "2022-04-27T00:32:50Z")

</div>

This is a good point! Suppose float lengths were allowed. Then if you wrote some code that computes the length of a range as a float and just happens to end up as an integer in your test cases. But then when you use your code in anger it doesn’t happen to compute an integer length anymore. Bam! It errors because the float cannot be converted to an integer value. In the current version on the other hand, you are forced to convert to explicitly convert to integer somehow even if the value happens to be integral, alerting you to the fact that this can fail or that rounding or flooring or whatever is necessary.

Of course traditional dynamic languages consider this situation above fine. Stuck a string in an array of integers? Guess you’ll find out eventually! But Julia tries to catch these things earlier by encouraging correct use of types. It catches it later than static languages but much earlier than untyped dynamic ones.

---

<div class="post-metadata">

**Author:** ![liuyxpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/liuyxpp/32/9870_2.png) [@liuyxpp](https://discourse.julialang.org/u/liuyxpp)\
**Post date:** [April 27, 2022, 2:13am UTC](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014/63 "2022-04-27T02:13:07Z")

</div>

I happened to find that `Union` is quite intuitive: when I first came across it, I get the idea and understand it without googling the doc.

[Previous page](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014.md?page=2)

[Next page](https://discourse.julialang.org/t/why-does-scientific-notation-break-the-range-function/80014.md?page=4)
