如何使用 .csv 文件中的 readtable 读取精确的小数位数?

How read the exact number of decimal digits with readtable from a .csv file?

我想使用函数 readtable 读取包含多位数字的 .csv 文件。然后我需要过滤一些行并将 table 导出到 .txt 文件。 我设法执行了此任务,但导出的文件包含的数字比存储在原始 .csv 文件中的数字少。

如何保持与原始文件中相同的小数位数?

这里是一个示例代码: “NEOs_asteroids.csv”附在这个问题上:

clear all; close all; clc;

%Data import from .CSV files
file_name_asteroids = 'NEOs_asteroids.csv';
%Asteroid data reading 
opts = delimitedTextImportOptions("NumVariables", 11);
% Specify range and delimiter
opts.DataLines = [2, Inf];
opts.Delimiter = ",";
% Specify column names and types
opts.VariableNames = ["pdes", "name", "epoch", "a", "e", "i", "om", "w", "ma", "q", "ad"];
opts.VariableTypes = ["string", "string", "double", "double", "double", "double", "double", "double", "double", "double", "double"];
% Specify file level properties
opts.ExtraColumnsRule = "ignore";
opts.EmptyLineRule = "read";
% Specify variable properties
opts = setvaropts(opts, ["pdes", "name"], "WhitespaceRule", "preserve");
opts = setvaropts(opts, ["pdes", "name"], "EmptyFieldRule", "auto");
% Import the data
Ast_data = readtable(file_name_asteroids,opts);

%%Data filtering
i_max = 5; % (deg) 
e_max = 0.1;
q_min = 0.9;  %(AU)
ad_max = 1.1; % (AU)
Ast_cond = Ast_data.i <= i_max & Ast_data.e <= e_max &...
                Ast_data.q >= q_min & Ast_data.ad <= ad_max;
Ast_data_filtered = Ast_data(Ast_cond,:);

%%Data export for Fortran calculations
% find empty cells
% emptyCells = cellfun(@isempty,Ast_data.name);
% Fill empty cells with a customized string
% Ast_data.name(emptyCells) = '(Empty cell)'

Output_file_name = 'NEOs_asteroids_filtered.txt';
writetable(Ast_data_filtered,Output_file_name,...
    "WriteVariableNames",true,"Encoding",'UTF-8',"Delimiter","comma");

这里是 .csv 文件“NEOs_asteroids.csv”(我只插入了几行,因为它们太多了):

"pdes","name","epoch","a","e","i","om","w","ma"
433,Eros,2459600.5,1.458273100364966,.2227273342470533,10.82846064209305,304.2963534821116,178.8971619902451,246.9041236220357
719,Albert,2459600.5,2.63750535267235,.5469586853330971,11.57526970278196,183.8552591536149,156.2275765643465,278.1971857577304
887,Alinda,2459600.5,2.473158049128383,.5704858457447907,9.394142747629626,110.4288007693465,350.4932417946612,86.60720939790032
1036,Ganymed,2459600.5,2.665849369179047,.5331216208605787,26.6779034163866,215.5172093946143,132.4281002671606,140.6548420252212
1221,Amor,2459600.5,1.918731194899893,.4358425037702864,11.88326264445768,171.320253219285,26.64392069638918,261.0445055510584
1566,Icarus,2459600.5,1.078092896249167,.8269435773988872,22.80421609750081,87.96160578064956,31.43750761745641,.3302900481594904
1580,Betulia,2459600.5,2.197288160959855,.4871550690589618,52.07925829047207,62.2921305585828,159.5134530240992,16.62891169416756
1620,Geographos,2459600.5,1.245689288382424,.3353623815747189,13.33753650197932,337.1849253154281,276.9463790257625,300.4925456677647
1627,Ivar,2459600.5,1.863273429711433,.3967369932429542,8.451956515515922,133.1203083485335,167.8035837515731,129.0289785118674
1685,Toro,2459600.5,1.367465568905196,.435966790549019,9.382739662870495,274.2362441040706,127.2114688956593,300.0617970060148
1862,Apollo,2459600.5,1.470502475713431,.5600430467767759,6.353083928279622,35.56898244993719,286.0386669340027,60.20237527657879
1863,Antinous,2459600.5,2.25922922966352,.6059920366929147,18.39886422664638,346.4237098245764,268.0896471241496,244.0101430178307
1864,Daedalus,2459600.5,1.460979692497152,.614486601048712,22.21536436924144,6.613194566464952,325.6563726322316,196.1166696209867
1865,Cerberus,2459600.5,1.079986459127503,.4669721847798676,16.09858904525619,212.8963846822369,325.2653260753237,170.2073771841984
1866,Sisyphus,2459600.5,1.893353802479725,.5383695942642949,41.20637430558688,63.47259682927852,293.0824330786623,331.1476239661798
1915,Quetzalcoatl,2459600.5,2.543790754476287,.5706410666538692,20.40472660837776,162.9348721741076,347.8091351438147,41.39145147165023
1916,Boreas,2459600.5,2.272324177667199,.4498393843780145,12.88297395642586,340.5981620510102,335.9167764123868,352.2401366045371
1917,Cuyo,2459600.5,2.149811212264342,.5054666607934076,23.95922692432141,188.2869783183211,194.5115030152427,82.28439227062766
1943,Anteros,2459600.5,1.430366783173011,.2560374828122278,8.706034969532251,246.3110706020363,338.3801329232052,173.8814283992249

您可能 运行 受到 MATLAB 内部使用的浮点格式的精度限制。 MATLAB 默认使用双精度来存储几乎所有数字。对于 IEEE double 你只会得到大约 15 decimal digits.

如果您不打算对这些数字执行计算,一个选项是 read them in as strings:

opts = detectImportOptions(filename);
opts = setvartype(opts, 'your variable', 'string');  % or 'char'
data = readtable(filename, opts);

如果你想对这些数字进行计算,事情会更难一些。 “built-in”选项是使用 Symbolic Math Toolbox 中的 variable-precision arithmetic,或者使用您自己的实现。我会考虑您是否真的首先需要精度,然后再沿着这些路径中的任何一条路径以获得更高的精度。