8

I searched and did not find similar answers which can resolve the 'no precision loss' issue. A sample string is:

"-5.100686209408900133332e+02 -1.294005398404007344443e+01 -2.59376479781563728887e+02 -1.3043629998334040122222e+02"

If I immediately convert them into real variable by ImportString or StringToDouble, then there will be precision loss, the resulted precision is only $MachinePrecision.

How to convert them into real number which should have higher precision than $MachinePrecision.

Yves Klett
  • 15,383
  • 5
  • 57
  • 124
LCFactorization
  • 3,047
  • 24
  • 37

2 Answers2

9

This question feels familiar but I could not find a true duplicate.

You can use the string replacement that Oleksandr proposed here and then use ToExpression to convert the numbers:

string = "-5.100686209408900133332e+02 -1.294005398404007344443e+01 \
-2.59376479781563728887e-02 -1.3043629998334040122222e+02"

ToExpression /@ StringReplace[StringSplit@string, "e" | "E" :> "*^"]
{-510.068620940890013333, -12.94005398404007344443, -0.025937647978156372889,
 -130.43629998334040122222}

Edit: a bug in verison 9 prevents the following solution from working.

Better I think, avoiding accidential code evaluation from ToExpression, you can use Read or ReadList with type Number, as I proposed for How do you convert a string containing a number in C scientific notation to a Mathematica number?:

# &[ReadList[#, Number], Close@#]& @ StringToStream @ string
{-510.068620940890013333, -12.94005398404007344443, -0.025937647978156372889,
 -130.43629998334040122222}

Note that # &[body, cleanup] is simply a way to evaluate cleanup after body, then return body.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • However, the further command causes: error message: `General::digit: "Digit at position 1 in !("-5.100686209408900133332") is too large to be used in base 10. "' – LCFactorization Dec 17 '13 at 10:01
  • @LCFactorization Please, what code causes that error? – Mr.Wizard Dec 17 '13 at 10:07
  • # &[ReadList[#, Number], Close@#]& @ StringToStream @ string will casue such error; others are OK. – LCFactorization Dec 17 '13 at 11:25
  • @LCF With what input? (What is assigned to string?) Which version are you using? I have not yet seen the error you describe. – Mr.Wizard Dec 17 '13 at 11:49
  • I use exactly the same `string = "-5.100686209408900133332e+02 -1.294005398404007344443e+01
    -2.59376479781563728887e-02 -1.3043629998334040122222e+02"'; the error persists
    – LCFactorization Dec 17 '13 at 11:53
  • @LCFactorization Okay, it must be a version difference. I'll see if I can get someone to look at that. – Mr.Wizard Dec 17 '13 at 11:56
  • Thank you very much. Probably this might be the reason – LCFactorization Dec 17 '13 at 12:06
  • 1
    Yes, this is a version difference. It stops working in version 9. I suspect a bug since the errors do not make sense and a very strange output is produced ({100*Removed["$$Failure"], 10*Removed["$$Failure"], Removed["$$Failure"]/100, 100*Removed["$$Failure"]}). – Oleksandr R. Dec 19 '13 at 11:48
  • @Mr.Wizard, I have same problem and using above mentioned code, I still get only till MachinePrecision in Mathematica v9.0, is there some improvement you can suggest?I cannot find anything anywhere about this topic. – jason Sep 01 '14 at 11:18
  • @jason does the StringReplace code at the top work correctly? – Mr.Wizard Sep 01 '14 at 11:21
  • @Mr.Wizard no it does not. It still gives me only MachinePrecision values – jason Sep 01 '14 at 11:24
4

The following is a place to start: Use StringToStream to convert the string data to an input stream:

num = "-5.100686209408900133332e+02 -1.294005398404007344443e+01
-2.59376479781563728887e+02 -1.3043629998334040122222e+02"

Now

str = StringToStream[num];

Use ReadList to read the InputStream

data = ReadList[str, Table[Record, {4}], RecordSeparators -> {" "}]; Close[str];

Here's the main trick to get your high precision Real

ReleaseHold[ToExpression[data, InputForm, Hold] /. {Plus[Times[x_, E | e], y_] :> x*10^y}]

Which gives:

{{-510.068620940890013333, -12.94005398404007344443, -259.37647978156372889,
 -130.43629998334040122222}}
RunnyKine
  • 33,088
  • 3
  • 109
  • 176