8
$\begingroup$

I noticed that Exp have a strange behaviour with big negative numbers

Exp[-Range[1, 700, 0.001]] // Developer`PackedArrayQ // AbsoluteTiming
Exp[-Range[1, 800, 0.001]] // Developer`PackedArrayQ // AbsoluteTiming

{0.014877, True}

{1.551377, False}

I understand than Exp[-800.0] is less than $MinMachineNumber, so I expected that the answer will be 0.0, but it is 3.668*10^-348 wich is not a machine number.

MachineNumberQ@Exp[-800.0]

False

What is the best way to work with these numbers? N@Exp do nothing.

My current solution is

NExp = Exp@Clip[#, {-100.0, 100.0}] &;

NExp[-Range[1, 800, 0.001]] // Developer`PackedArrayQ // AbsoluteTiming

{0.016354, True}

Moreover, I notice that Exp works fine with complex numbers (only in v9)

Exp[0.0 I - Range[1, 700, 0.001]] // Developer`PackedArrayQ // AbsoluteTiming
Exp[0.0 I - Range[1, 800, 0.001]] // Developer`PackedArrayQ // AbsoluteTiming

{0.049367, True}

{0.066757, True}

Edit:

I saw the answer with suggestion of compilation but for some reason it was removed. It is not very fast solution but it works. So I post it here

NExp = Compile[{{x, _Real}}, Exp[x], RuntimeAttributes -> {Listable}];

NExp[-Range[1, 800, 0.001]]) // Developer`PackedArrayQ // AbsoluteTiming

{0.114772, True}

$\endgroup$
4
  • $\begingroup$ You mean, you want numbers outside the machine number zone to be clipped and kept as machine numbers? $\endgroup$
    – Rojo
    Sep 8, 2013 at 0:26
  • $\begingroup$ @Rojo Yes, it is. I want it to be automatically and will not unpack arrays. Values like Exp[-800] appears in the studying something like Fermi-Dirac distribution for small temperatures. But these values is just zero. $\endgroup$
    – ybeltukov
    Sep 8, 2013 at 1:18
  • $\begingroup$ In version 7 I get {0.0080005, True} and {0.0160009, True} as the output of the first two lines. Apparently this is version specific; what are you running? $\endgroup$
    – Mr.Wizard
    Sep 8, 2013 at 8:00
  • $\begingroup$ @Mr.Wizard I ran it in v9, but in v7 I have the same result. May be it is platform-specific? I have Gentoo Linux. $\endgroup$
    – ybeltukov
    Sep 8, 2013 at 11:16

1 Answer 1

0
$\begingroup$

Will something like this work?

SetPrecision[Chop[N@#], MachinePrecision] & /@ Exp[-Range[1, 800]] //
   Developer`ToPackedArray // Developer`PackedArrayQ // AbsoluteTiming
{0.004003, True}

The number has to first be converted to a numerical form with N or Chop won't do anything to it. Even if the number is large enough it isn't guaranteed to be converted to a machine precision number so we force that by calling SetPrecision. Conversion to a packed array isn't guaranteed either, so we have to call ToPackedArray. But, ToPackedArray won't convert a list if there will be a precision loss.

For a single value the following returns True.

MachineNumberQ@SetPrecision[Chop[N@Exp[-800]], MachinePrecision]
True
$\endgroup$
1
  • $\begingroup$ This is interesting solution, but for my Range[1,800,0.001] it tooks about 3 seconds. It is 200 times slower than my solution... $\endgroup$
    – ybeltukov
    Sep 8, 2013 at 11:10

Not the answer you're looking for? Browse other questions tagged or ask your own question.