Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Suppose I have a string containing the C-representation of a floating point number, for example

s = "1.23e-5"

and I want to convert this to a Mathematica number. How can I do this?

ToExpression[s] gives Plus[-5, Times[1.23`, e]].

share|improve this question
    
The only way I know how to do this is ImportString["1.23e-5","Table"][[1,1]] which seems like rather a large hack! –  Ian Hinder Feb 14 '12 at 13:13
add comment

5 Answers

up vote 30 down vote accepted

I think probably the cleanest way to do this (at least, if you have only a single string, or are faced with a separate string for each number you wish to convert as a result of some other process) is to use the undocumented function Internal`StringToDouble, i.e.:

s = "1.23e-5";
Internal`StringToDouble[s]

which gives:

0.0000123

However, if you are trying to convert many such numbers at once, the standard, documented methods (Import, Read, etc.), are likely to represent better approaches.

share|improve this answer
8  
Another one from Mr.Undocumented! –  rm -rf Feb 14 '12 at 15:32
3  
Always try to avoid ToExpression! –  FJRA Feb 14 '12 at 17:37
1  
This seems like functionality that should be available (officially) in Mathematica. Will Wolfram accept feature-requests? –  Ian Hinder Feb 23 '12 at 16:06
    
@FJRA Why should ToExpression be avoided? –  George Wolfe Oct 17 '12 at 16:19
2  
@GeorgeWolfe because it might lead you to a code leak. What if there is dangerous code within the string? Or something innocent like a equal sign (=) may set any of your variables. –  FJRA Oct 18 '12 at 20:34
add comment

On version 7 Internal`StringToDouble fails on long strings, and fails to recognize exponents:

Internal`StringToDouble["3.1415926535897932385"]

Internal`StringToDouble /@ {"3.14159", "3.14159e-02", "3.14159e+02"}
$Failed["Bignum"]

{3.14159, 3.14159, 3.14159}

This sent me looking for another way to convert numeric strings. Using Trace on ImportString I found another internal function that does what I need: System`Convert`TableDump`ParseTable.

Being an internal function is it not error tolerant and if fed bad arguments it will crash the kernel. The syntax is as follows:

System`Convert`TableDump`ParseTable[
  table,
  {{pre, post}, {neg, pos}, dot},
  False
]
table  :   table of strings, depth = 2; need not be rectangular.  
pre    :   List of literal strings to ignore if preceding the digits (only first match tried).  
post   :   List of literal strings to ignore if following the digits (only first match tried).  
neg    :   literal string to interpret a negative sign (`-`).  
pos    :   literal string to interpret a positive sign (`+`).  
dot    :   literal string to interpret as decimal point.

(Using True in place of False causes a call to System`Convert`TableDump`TryDate that I do not yet understand.)

Example:

System`Convert`TableDump`ParseTable[
  {{"-£1,234.141592653589793e+007"}, {"0.97¢", "140e2kg"}},
  {{{"£"}, {"kg", "¢"}}, {"-", "+"}, "."},
  False
]

{{-1.2341415926535898*^10}, {0.97, 14000.}}

share|improve this answer
    
Ah, kernel spelunking, +1. –  rcollyer Aug 20 '12 at 14:49
2  
Nice work! I'm sure this function will be useful. Regarding Internal`StringToDouble on 7: exponents are recognised if you first use StringReplace[nums, "e"|"E" -> "*^"]. –  Oleksandr R. Aug 21 '12 at 23:54
    
@Oleksandr thanks, and good to know about StringToDouble! –  Mr.Wizard Aug 22 '12 at 4:49
    
ParseTable is great. Very fast and handles integers as well as reals. I've used it a bunch of times when I know my input is clean, thanks a bunch! –  ssch Dec 7 '13 at 14:30
    
@ssch Glad I could help. :-) –  Mr.Wizard Dec 7 '13 at 18:25
add comment
s = "1.23e-5"

# &[Read[#, Number], Close@#]&[ StringToStream@s ]

Which is not as good as what you started with. Note that it is important to close the stream.


Szabolcs says this is difficult to read. That was surely not my intention. You could also write it verbosely like this:

fromC =
    Module[{output, stream},
      stream = StringToStream[#];
      output = Read[stream, Number];
      Close[stream];
      output
    ] &;

fromC[s]
share|improve this answer
add comment

May be one can try the following

convert[inp_?StringQ] := ToExpression@StringReplace[inp, "e" -> "*10^"];
share|improve this answer
    
Still this is not fully correct! If numbers like 2.12 is represented as "2.12e" than the expected "2.12e1". MMA does so as I mentioned in the above comment on the answer given by @J.M –  PlatoManiac Feb 14 '12 at 13:51
7  
It works, but let me give one comment: whenever you use ToExpression on data read from a file, you make it possible to inject code into a program even inadvertently (one can never tell what sort of erroneous input the program might get by mistake). I generally try not to use ToExpression for just reading in data (as opposed to converting code) –  Szabolcs Feb 14 '12 at 13:55
    
@Szabolcs thanks for explaining the issue with ToExpression. Your implementation is pretty cool. I did not know about the function StringToStream thanks for introducing... –  PlatoManiac Feb 14 '12 at 14:01
add comment

First[ImportString["1.23e-5", "List"]] might be slightly less hack-y than your suggestion in the comments...

share|improve this answer
    
What about a string like "2.12e"? You can see in MMA examples where such strings are generated as CForm/FortranForm ScientificForm[2.12, NumberFormat -> (Row[{#1, "e", #3}] &)] –  PlatoManiac Feb 14 '12 at 13:47
    
@Plato is that a standard form? It looks like an error. –  Mr.Wizard Feb 14 '12 at 13:53
    
@Plato: That's funny; I don't think I've ever seen a superfluous e being added to numbers between $1$ and $10$, I must say. Neither CForm[] nor FortranForm[] do this, and ScientificForm[] will only do that if you mess with options like you have. –  J. M. Feb 14 '12 at 13:54
    
@J.M. You are right! It does not generate numbers that ends with such a "e" as I wrote. Actually I got misled by the documentation of ScientificForm. You can also check there the NumberFormat example in the Options section of the documentation for ScientificForm. There they show how to produce Fortran-like forms. Test with a number like "2.12" and see the foolish "e" appears. But it is indeed not a general truth about the CFormor FortranForm. –  PlatoManiac Feb 14 '12 at 14:07
    
@Plato: Okay, but I think that's a rather contrived example. I don't think I've seen an entity like 2.12e in applications... –  J. M. Feb 14 '12 at 14:19
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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