# Exp of big negative numbers [duplicate]

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

Exp[-Range[1, 700, 0.001]] // DeveloperPackedArrayQ // AbsoluteTiming
Exp[-Range[1, 800, 0.001]] // DeveloperPackedArrayQ // 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]] // DeveloperPackedArrayQ // 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]] // DeveloperPackedArrayQ // AbsoluteTiming
Exp[0.0 I - Range[1, 800, 0.001]] // DeveloperPackedArrayQ // 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]]) // DeveloperPackedArrayQ // AbsoluteTiming


{0.114772, True}

-
You mean, you want numbers outside the machine number zone to be clipped and kept as machine numbers? –  Rojo Sep 8 '13 at 0:26
@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. –  ybeltukov Sep 8 '13 at 1:18
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? –  Mr.Wizard Sep 8 '13 at 8:00
@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. –  ybeltukov Sep 8 '13 at 11:16

## marked as duplicate by Simon Woods, rm -rf♦Sep 8 '13 at 15:15

Will something like this work?

SetPrecision[Chop[N@#], MachinePrecision] & /@ Exp[-Range[1, 800]] //
DeveloperToPackedArray // DeveloperPackedArrayQ // 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

-
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... –  ybeltukov Sep 8 '13 at 11:10