2

I wanted to put some FrameTicks to a Plot with

xticks = Range[-2, 2, 0.2]

and got

{-2., -1.8, -1.6, -1.4, -1.2, -1., -0.8, -0.6, -0.4, -0.2, 
1.11022*10^-16, 0.2, 0.4, 0.6, 0.8, 1., 1.2, 1.4, 1.6, 1.8, 2.}

so there is the small number instead of the zero.

Using Table gives the same output:

Table[k, {k, -2, 2, 0.2}]
{-2., -1.8, -1.6, -1.4, -1.2, -1., -0.8, -0.6, -0.4, -0.2, 
1.11022*10^-16, 0.2, 0.4, 0.6, 0.8, 1., 1.2, 1.4, 1.6, 1.8, 2.}

But using 0.25 as the step value, everything is fine:

xticks = Range[-2, 2, 0.25]
{-2., -1.75, -1.5, -1.25, -1., -0.75, -0.5, -0.25, 0., 0.25, 0.5, \
0.75, 1., 1.25, 1.5, 1.75, 2.}

How to replace the small number and set it to zero?

Chris Degnen
  • 8,443
  • 2
  • 23
  • 40
  • FWIW Mathematica v9 actually is smart enough to handle this. What version do you have? (Both `Table` and `Range` give an exact zero ). I would still advise using the approaches in @TobiaTesan answer however. – agentp Jul 27 '15 at 14:24

1 Answers1

2

TL;DR:

Consider using:

Range[-20, 20, 2]/10

optionally converting them to floating point with:

N[Range[-20, 20, 2]/10]`

What's actually going on with the 0:

Range[-2, 2, 0.2] uses floating point arithmetic, so at some point it gets to some n which is a floating point approximation of -0.2 and adds 0.2f: the result cannot possibly be 0 - we are in the domain F -, it can at best be 0. or some other reasonably close approximant (see also: The difference between 0. and 0).

How close is "reasonably close", though?

Floating point subtraction between really close values is notoriously tricky, and that's probably why 2.0, 1.8, ... look fine but your approximant for zero, obtained by -0.2f + 0.2f, is ugly.

On the other hand, Range[-20, 20, 2] works with natural numbers and -2 + 2 in N is plain 0 (fixed precision arithmetic is not nearly as tricky as floating point).

Then Range[-20, 20, 2]/10 maps to Q (where any p/q with p = 0 still easily evaluates to 0).

You can also chop your floats to arbitrary precision with Chop[Range[-2, 2, 0.2]].

Community
  • 1
  • 1
Tobia Tesan
  • 1,938
  • 17
  • 29
  • Thank you for your detailed explanation. Now I see the difference of domains Real and Integer. The Chop[Range[-2, 2, 0.2]] works for me, because I wanted to have Numbers instead of fractions in my ticks. – edwin bubble Jul 26 '15 at 14:32
  • @edwinbubble glad to help. Feel free to accept this answer by clicking on the v-tick icon :) – Tobia Tesan Jul 26 '15 at 14:34
  • But I can't get the point why 0.25 works, while 0.2 doesn't? Both numbers are of the same kind, namely rational... – edwin bubble Jul 26 '15 at 14:38
  • @edwinbubble: `0.2` "works" as well, `1.11022*10^-16` is a reasonably good approximant of *the* `0` - it is only `1.11022*10^-16` off from `0.`, after all :) Why the `0.25` sequence yields a marginally better approximation I can't say, you'd have to look at your hardware and at the exact (family of) algorithms Mathematica uses (e.g.: on my machine, I get `0.`). I think "blind luck" is a sufficiently good explanation, once we know *why* `0.2 - 0.2` is not that accurate. Note that `0.25` is `2^-2`, which is a very nice number to start with. If you are so inclined, make some experiments :) – Tobia Tesan Jul 26 '15 at 14:44
  • 1
    not luck, .25 being a power of 2 is exactly represented in floating point – agentp Jul 27 '15 at 11:36
  • @agentp: yes, my point was that OP shouldn't probably overanalyze this, though - it's **not "broken"** :) – Tobia Tesan Jul 27 '15 at 11:48
  • 1
    Thanks you both, now I got the point. Maybe I was over-analyzing, but I was just curious. Once understood one can go one... – edwin bubble Jul 27 '15 at 12:32