# How do I convert an inexact number smaller than $MinMachineNumber to machine-precision? I was trying to convert some arbitrary-precision numbers to machine-precision numbers using N[myNumber,MachinePrecision]. But, although my test number did lose some precision, it still had a very strange exponent: number = 5.80373641176129118633405301544668516*^-400; number1 = SetPrecision[number, MachinePrecision]  5.803736411761291×10^-400 As$10^{-400}$is not representable in IEEE 754 binary64, and I'm on x86 where this format is native, I tried checking what precision the number has, and it appears Precision@number1  15.954589770191 This might be OK if truly machine-precision numbers gave the same, but they don't: Precision@1.5  MachinePrecision Finally, I've checked my number given by SetPrecision using FullForm: FullForm@number1  5.80373641176129118633405301544668515.954589770191005*^-400 So, apparently, SetPrecision won't give me machine number. How then do I convert my arbitrary-precision number to machine number? (I'd expect the$~10^{-400}$value to be rounded down to machine zero.) • N[number]?? From Documentation Center page "MachinePrecision": "MachinePrecision is the symbol representing the number of decimal digits used by numerical functions such as N, NIntegrate, and NSum in the Wolfram Language for machine-precision computations." – murray Nov 30 '17 at 22:03 • @murray have you actually tried it? Its result is not different from that from SetPrecision[number,MachinePrecision]. – Ruslan Dec 1 '17 at 6:02 • Related: (37764) – Mr.Wizard Jul 24 '18 at 4:47 ## 4 Answers This situation is comparable to $MinMachineNumber / 2


automatically giving an arbitrary precision result.

Precision[$MinMachineNumber/2] (* 15.9546 *)  Mathematica detects the underflow condition and switches to arbitrary precision arithmetic. This can be turned off: SetSystemOptions["CatchMachineUnderflow" -> False]  Now the result of $MinMachineNumber/2 has MachinePrecision. The result is not 0., but a denormal number, I believe (my knowledge is lacking in this area). If you divide by a number larger than 10^$MachinePrecision then you get a 0.. $MinMachineNumber/2
(* 1.11254*10^-308 *)

$MinMachineNumber/10^15 (* 2.5*10^-323 *)$MinMachineNumber/10^16
(* 0. *)


SetPrecision works as you want it, too.

number = 5.80373641176129118633405301544668516*^-400;
number1 = SetPrecision[number, MachinePrecision]
(* 0. *)


SetPrecision will not create denormal numbers, it seems.

SetPrecision[1.216*^-308, MachinePrecision]
(* 0. *)

• With V11.1.1 running on OS X 10.10.2, I do not get the OP's result from SetPrecision, not yours. – m_goldberg Dec 1 '17 at 6:06
• Wow never supposed Mathematica would use allow denormals (they are performance killers for machine-precision computations). Is there any way to enable Flush-To-Zero mode in Mathematica (other than attaching a debugger and change MXCSR manually :) )? – Ruslan Dec 1 '17 at 6:14
• @m_goldberg Sorry, I do not understand. What do you get precisely when underflow checking is enabled/disabled? – Szabolcs Dec 1 '17 at 7:13
• I did not read your post carefully enough to realize the results you showed applied to the case where catching machine overflow had been turned off. – m_goldberg Dec 2 '17 at 0:18
number = 5.80373641176129118633405301544668516*^-400;
number + 0.
(* 0. *)


N makes arbitrary precision numbers when either given a second argument or a number not representable by a machine number as its first argument. However, machine numbers in expressions generally coerce arithmetic into the machine domain.

Another way:

toMPReal = Compile[x, x][#] &(*/.c_Compile :> RuleCondition[c]*);

toMPReal[5.80373641176129118633405301544668516*^-400]
(*  0.  *)


Uncomment the replacement rule to pre-compile the function.

Starting in M11.3, SetPrecision will always produce a machine number when the second argument is MachinePrecision. The documentation for SetPrecision was unfortunately not updated with this change. Also, this means that the system option SetSystemOptions["CatchMachineUnderflow" -> True] no longer does anything. So, now you get the desired behavior without modifying any system options:

number = 5.80373641176129118633405301544668516*^-400;
number1 = SetPrecision[number,MachinePrecision]
`

0.