Write float arrays to a text file
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Write two equal-sized numerical arrays `x' and `y' to a two-column text file named `filename'.
The first column of the file contains values from an `x'-array with a given `xprecision', the second -- values from `y'-array with `yprecision'.
For example, considering:
x = {1, 2, 3, 1e11};
y = {1, 1.4142135623730951, 1.7320508075688772, 316227.76601683791}; /* sqrt(x) */
xprecision = 3;
yprecision = 5;
The file is:
1 1 2 1.4142 3 1.7321 1e+011 3.1623e+005
This task is intended as a subtask for Measure relative performance of sorting algorithms implementations.
Contents |
[edit] Ada
with Ada.Text_IO; use Ada.Text_IO; with Ada.Float_Text_IO; use Ada.Float_Text_IO; with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions; procedure Write_Float_Array is type Float_Array is array (1..4) of Float; procedure Write_Columns ( File : File_Type; X : Float_Array; Y : Float_Array; X_Pres : Natural := 3; Y_Pres : Natural := 5 ) is begin for I in Float_Array'range loop Put (File => File, Item => X(I), Fore => 1, Aft => X_Pres - 1); Put (File, " "); Put (File => File, Item => Y(I), Fore => 1, Aft => Y_Pres - 1); New_Line (File); end loop; end Write_Columns; File : File_Type; X : Float_Array := (1.0, 2.0, 3.0, 1.0e11); Y : Float_Array; begin Put ("Tell us the file name to write:"); Create (File, Out_File, Get_Line); for I in Float_Array'range loop Y(I) := Sqrt (X (I)); end loop; Write_columns (File, X, Y); Close (File); end Write_Float_Array;
[edit] ALGOL 68
PROC writedat = (STRING filename, []REAL x, y, INT x width, y width)VOID: (
FILE f;
INT errno = open(f, filename, stand out channel);
IF errno NE 0 THEN stop FI;
FOR i TO UPB x DO
# FORMAT := IF the absolute exponent is small enough, THEN use fixed ELSE use float FI; #
FORMAT repr x := ( ABS log(x[i])<x width | $g(-x width,x width-2)$ | $g(-x width,x width-4,-1)$ ),
repr y := ( ABS log(y[i])<y width | $g(-y width,y width-2)$ | $g(-y width,y width-4,-1)$ );
putf(f, (repr x, x[i], $" "$, repr y, y[i], $l$))
OD;
close(f)
);
Example usage:
[]REAL x = (1, 2, 3, 1e11);
[UPB x]REAL y; FOR i TO UPB x DO y[i]:=sqrt(x[i]) OD;
printf(($"x before:"$, $xg$, x, $l$));
printf(($"y before:"$, $xg$, y, $l$));
writedat("sqrt.dat", x, y, 3+2, 5+2);
printf($"After:"l$);
FILE sqrt dat;
INT errno = open(sqrt dat, "sqrt.dat", stand in channel);
IF errno NE 0 THEN stop FI;
on logical file end(sqrt dat, (REF FILE sqrt dat)BOOL: stop);
TO UPB x DO
STRING line;
get(sqrt dat, (line, new line));
print((line,new line))
OD
Output:
x before: +1.00000000000000e +0 +2.00000000000000e +0 +3.00000000000000e +0 +1.00000000000000e +11 y before: +1.00000000000000e +0 +1.41421356237310e +0 +1.73205080756888e +0 +3.16227766016838e +5 After: 1.000 1.00000 2.000 1.41421 3.000 1.73205 1e11 316228
[edit] C
#include <stdio.h> #include <math.h> int main(int argc, char **argv) { float x[4] = {1,2,3,1e11}, y[4]; int i = 0; FILE *filePtr; filePtr = fopen("floatArray","w"); for (i = 0; i < 4; i++) { y[i] = sqrt(x[i]); if (x[i] > 10000 || x[i] < .00001 || y[i] > 10000 || y[i] < .00001) { /* profoundly arbitrary on my part */ fprintf(filePtr, "%1.3e\t%1.5e\n", x[i], y[i]); } else { fprintf(filePtr, "%1.3f\t%1.5f\n", x[i], y[i]); } } return 0; }
The file "floatArray" then contains the following:
1.000 1.00000 2.000 1.41421 3.000 1.73205 1.000e+11 3.16228e+05
[edit] C++
Function writedat():
template<class InputIterator, class InputIterator2> void writedat(const std::string& filename, InputIterator xbegin, InputIterator xend, InputIterator2 ybegin, InputIterator2 yend, int xprecision=3, int yprecision=5) { std::ofstream f; f.exceptions(std::ofstream::failbit | std::ofstream::badbit); f.open(filename.c_str()); for ( ; xbegin != xend and ybegin != yend; ++xbegin, ++ybegin) f << std::setprecision(xprecision) << *xbegin << "\t" << std::setprecision(yprecision) << *ybegin << "\n"; }
Example:
#include <algorithm> #include <cmath> #include <fstream> #include <iomanip> #include <iostream> #include <iterator> // back_inserter() #include <string> #include <vector> int main() { try { // prepare test data double x[] = {1, 2, 3, 1e11}; const size_t xsize = sizeof(x) / sizeof(*x); std::vector<double> y; std::transform(&x[0], &x[xsize], std::back_inserter(y), ::sqrt); // write file using default precisions writedat("sqrt.dat", &x[0], &x[xsize], y.begin(), y.end()); // print the result file std::ifstream f("sqrt.dat"); for (std::string line; std::getline(f, line); line.clear()) std::cout << line << std::endl; } catch(std::exception& e) { std::cerr << "writedat: exception: '" << e.what() << "'\n"; return 1; } return 0; }
Result:
1 1 2 1.4142 3 1.7321 1e+11 3.1623e+05
[edit] Fortran
In ANSI FORTRAN 77 or later use OPEN STATEMENT, and formatted WRITE statement with implied DO loop:
real x(4), y(4)
data x / 1.0, 2.0, 4.0, 1.0e11 /
do 10 i = 1, 4
y = sqrt(x)
10 continue
open(unit=15, file='two_cols.txt', status='new')
write(15,'(f20.3,f21.4)') (x(I), y(I), I = 1, 4)
end
[edit] Haskell
Probably not very idiomatic but oh well
import System.IO
import Text.Printf
import Control.Monad
writeDat filename x y xprec yprec =
do h <- openFile filename WriteMode
-- Haskell's printf doesn't support a precision given as an argument for some reason, so we insert it into the format manually:
let writeLine = hPrintf h ("%." ++ show xprec ++ "g\t%." ++ show yprec ++ "g\n")
zipWithM_ writeLine x y
hClose h
Example usage
Prelude> let x = [1, 2, 3, 1e11] Prelude> let y = map sqrt x Prelude> y [1.0,1.4142135623730951,1.7320508075688772,316227.7660168379] Prelude> writeDat "sqrt.dat" x y 3 5 Prelude> readFile "sqrt.dat" >>= putStr 1.000 1.00000 2.000 1.41421 3.000 1.73205 1.000e11 316227.76602
[edit] IDL
; the data:
x = [1,2,3,1e11]
y=sqrt(x)
xprecision=3
yprecision=5
; NOT how one would do things in IDL, but in the spirit of the task - the output format:
form = string(xprecision,yprecision,format='("(G0.",I0.0,",1x,G0.",I0.0,")")')
; file I/O:
openw,unit,"datafile.txt",/get
for i = 1L, n_elements(x) do printf, unit, x[i-1],y[i-1],format=form
free_lun,unit
The file "datafile.txt" then contains the following:
1 1 2 1.4142 3 1.7321 1E+011 3.1623E+005
This is fairly ugly and un-IDLish. For example one shouldn't just rely on x and y having the same size. And if data is output in human-readable form, it should probably be lined up more nicely. And if it really has to be in two-column format with x and y side by side, one might consider running ASCII_Template or some such instead of that ugly hand-formatting.
[edit] J
require 'files' NB. for fwrites x =. 1 2 3 1e11 y =. %: x NB. y is sqrt(x) xprecision =. 3 yprecision =. 5 filename =. 'whatever.txt' data =. (0 j. xprecision,yprecision) ": x,.y data fwrites filename
[edit] OCaml
let write_dat filename x y ?(xprec=3) ?(yprec=5) () = let oc = open_out filename in let write_line a b = Printf.fprintf oc "%.*g\t%.*g\n" xprec a yprec b in List.iter2 write_line x y; close_out oc
Example usage
# let x = [1.0; 2.0; 3.0; 1e11];;
val x : float list = [1.; 2.; 3.; 100000000000.]
# let y = List.map sqrt x;;
val y : float list =
[1.; 1.41421356237309515; 1.73205080756887719; 316227.766016837908]
# write_dat "sqrt.dat" x y ();;
- : unit = ()
# let ic = open_in "sqrt.dat";;
val ic : in_channel = <abstr>
# try
while true do
print_endline (input_line ic)
done
with End_of_file -> ();;
1 1
2 1.4142
3 1.7321
1e+11 3.1623e+05
- : unit = ()
[edit] Python
Works with: Python version 2.6
import itertools def writedat(filename, x, y, xprecision=3, yprecision=5): with open(filename,'w') as f: for a, b in itertools.izip(x, y): f.write("%.*g\t%.*g\n" % (xprecision, a, yprecision, b))
Example usage
>>> import math >>> x = [1, 2, 3, 1e11] >>> y = map(math.sqrt, x) >>> y [1.0, 1.4142135623730951, 1.7320508075688772, 316227.76601683791] >>> writedat("sqrt.dat", x, y) >>> # check ... >>> for line in open('sqrt.dat'): ... print line, ... 1 1 2 1.4142 3 1.7321 1e+011 3.1623e+005
[edit] Ruby
# prepare test data x = [1, 2, 3, 1e11] y = x.collect { |xx| Math.sqrt xx } xprecision = 3 yprecision = 5 # write the arrays open('sqrt.dat', 'w') do |f| x.zip(y) { |xx, yy| f.printf("%.*g\t%.*g\n", xprecision, xx, yprecision, yy) } end # print the result file open('sqrt.dat', 'r') { |f| puts f.read }
Result:
1 1 2 1.4142 3 1.7321 1e+11 3.1623e+05
Categories: Programming Tasks | Solutions by Programming Task | Ada | ALGOL 68 | C | C++ | Fortran | Haskell | IDL | J | OCaml | Python | Ruby

