Write float arrays to a text file
From Rosetta Code
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] AWK
As usual, the order of array traversal in AWK is not necessarily the same as the input had:
$ awk 'BEGIN{split("1 2 3 1e11",x);
> split("1 1.4142135623730951 1.7320508075688772 316227.76601683791",y);
> for(i in x)printf("%6g %.5g\n",x[i],y[i])}'
1e+11 3.1623e+05
1 1
2 1.4142
3 1.7321
For the text file part of the task, just redirect stdout to it.
[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] c99 version
/** gcc -Wall -std=c99 *.c -o a && a */
#include <limits.h> // LINE_MAX, see http://www.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
#ifndef LINE_MAX
# define LINE_MAX 2048
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h> // exit()
static int
writedat(size_t n; const char* filename, double x[n], double y[n], size_t n,
int xprecision, int yprecision)
{
FILE* f = NULL;
if ((f = fopen(filename, "w")) == NULL) goto error;
for (size_t i = 0; i < n; ++i)
if (fprintf(f, "%.*g\t%.*g\n", xprecision, x[i], yprecision, y[i]) < 0)
goto error;
if (fclose(f) == EOF) goto error;
return 0; // ok
error:
//NOTE: caller of this function should deal with `errno` on error
return 1; // error
}
int
main(int argc, char **argv)
{
// prepare test data
double x[] = {1,2,3,1e11};
const size_t xsize = sizeof(x) / sizeof(*x);
double y[xsize];
for (size_t i = 0; i < xsize; i++) y[i] = sqrt(x[i]);
// write arrays
const char* filename = "sqrt.dat";
const int save_errno = errno;
errno = 0;
if (writedat(filename, x, y, xsize, 3, 5) != 0) {
perror("writedat"); exit(1);
}
errno = save_errno;
// print the result file
FILE* f = NULL;
if ((f = fopen(filename, "r")) == NULL) exit(1);
char line[LINE_MAX];
while (fgets(line, LINE_MAX, f) != NULL)
fputs(line, stdout);
/* int c = EOF; */
/* while ((c = fgetc(f)) != EOF) */
/* putchar(c); */
return 0;
}
It prints:
1 1 2 1.4142 3 1.7321 1e+011 3.1623e+005
[edit] C++
Function writedat():
template<class InputIterator, class InputIterator2>
void writedat(const char* 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);
for ( ; xbegin != xend and ybegin != yend; ++xbegin, ++ybegin)
f << std::setprecision(xprecision) << *xbegin << '\t'
<< std::setprecision(yprecision) << *ybegin << '\n';
}
Example:
#include <algorithm>
#include <cmath> // ::sqrt()
#include <fstream>
#include <iomanip> // setprecision()
#include <iostream>
#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(xsize);
std::transform(&x[0], &x[xsize], y.begin(), ::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); )
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] Common Lisp
(with-open-file (stream (make-pathname :name "filename") :direction :output)
(let* ((x (make-array 4 :initial-contents '(1 2 3 1e11)))
(y (map 'vector 'sqrt x))
(xprecision 3)
(yprecision 5)
(fmt (format nil "~~,1,~d,,G~~12t~~,~dG~~%" xprecision yprecision)))
(map nil (lambda (a b)
(format stream fmt a b)) x y)))
Using CLISP I get
1. 1.0000 2. 1.4142 3. 1.7321 1.0E+011 3.16228E+5
[edit] D
import std.file;
import std.string;
void main() {
double[]x = [1.0,2,3,1e11];
double[]y = [1.0, 1.4142135623730951, 1.7320508075688772, 316227.76601683791];
int xprecision = 3,yprecision = 5;
char[]tmp;
foreach(i,fx;x) {
tmp ~= format("%."~toString(xprecision)~"g %."~toString(yprecision)~"g\r\n",fx,y[i]);
}
write("floatarray.txt",tmp);
}
output is: 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
Works with: Fortran version 90 and later
program writefloats
implicit none
real, dimension(10) :: a, sqrta
integer :: i
integer, parameter :: unit = 40
a = (/ (i, i=1,10) /)
sqrta = sqrt(a)
open(unit, file="xydata.txt", status="new", action="write")
call writexy(unit, a, sqrta)
close(unit)
contains
subroutine writexy(u, x, y)
real, dimension(:), intent(in) :: x, y
integer, intent(in) :: u
integer :: i
write(u, "(2F10.4)") (x(i), y(i), i=lbound(x,1), ubound(x,1))
end subroutine writexy
end program writefloats
The arrays x and y should have same bounds (and size); this constraint is not checked.
[edit] Haskell
Probably not very idiomatic but oh well
import System.IO
import Text.Printf
import Control.Monad
writeDat filename x y xprec yprec =
withFile filename WriteMode $ \h ->
-- 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") in
zipWithM_ writeLine x y
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] Java
import java.io.*;
public class FloatArray {
public static void writeDat(String filename, double[] x, double[] y,
int xprecision, int yprecision)
throws IOException {
assert x.length == y.length;
PrintWriter out = new PrintWriter(filename);
for (int i = 0; i < x.length; i++)
out.printf("%."+xprecision+"g\t%."+yprecision+"g\n", x[i], y[i]);
out.close();
}
public static void main(String[] args) {
double[] x = {1, 2, 3, 1e11};
double[] y = new double[x.length];
for (int i = 0; i < x.length; i++)
y[i] = Math.sqrt(x[i]);
try {
writeDat("sqrt.dat", x, y, 3, 5);
} catch (IOException e) {
System.err.println("writeDat: exception: "+e);
}
try {
BufferedReader br = new BufferedReader(new FileReader("sqrt.dat"));
String line;
while ((line = br.readLine()) != null)
System.out.println(line);
} catch (IOException e) { }
}
}
[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] Perl
sub writedat {
my ($filename, $x, $y, $xprecision, $yprecision) = @_;
open FH, ">", $filename or die "Can't open file: $!";
printf FH "%.*g\t%.*g\n", $xprecision||3, $x->[$_], $yprecision||5, $y->[$_] for 0 .. $#$x;
close FH;
}
my @x = (1, 2, 3, 1e11);
my @y = map sqrt, @x;
writedat("sqrt.dat", \@x, \@y);
File contents
1 1 2 1.4142 3 1.7321 1e+11 3.1623e+05
[edit] PL/I
declare X(5) float (9) initial (1, 2, 3, 4, 5),
Y(5) float (18) initial (9, 8, 7, 6, 1e9);
declare (x_precision, y_precision) fixed binary;
open file (out) title ('/OUT.TXT,type(text),recsize(100)');
x_precision = 9;
y_precision = 16;
put file (out) edit ((X(i), Y(i) do i = 1 to 5))
(skip, e(16, x_precision),
x(2), e(20, y_precision) );
[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):
print >> f, "%.*g\t%.*g" % (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
Works with: Python version 3
def writedat(filename, x, y, xprecision=3, yprecision=5):
with open(filename,'w') as f:
for a, b in zip(x, y):
print("%.*g\t%.*g" % (xprecision, a, yprecision, b), file=f)
#or, using the new-style formatting:
#print("{1:.{0}g}\t{3:.{2}g}".format(xprecision, a, yprecision, b), file=f)
[edit] R
writexy <- function(file, x, y, xprecision=3, yprecision=3)
{
#Format inputs as required, and join together
fx <- formatC(x, digits=xprecision, format="g", flag="-")
fy <- formatC(y, digits=yprecision, format="g", flag="-")
dfr <- data.frame(fx, fy)
#Write to file. Note that this encloses the formatted number in quotes,
write.table(dfr, file=file, sep="\t", row.names=FALSE)
#... so we have to process the output
str <- readLines(file)
writeLines(gsub('"', '', str), file)
}
x <- c(1, 2, 3, 1e11)
y <- sqrt(x)
writexy('test.txt', x, y, yp=5)
[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
[edit] Standard ML
fun writeDat (filename, x, y, xprec, yprec) = let
val os = TextIO.openOut filename
fun write_line (a, b) =
TextIO.output (os, Real.fmt (StringCvt.GEN (SOME xprec)) a ^ "\t" ^
Real.fmt (StringCvt.GEN (SOME yprec)) b ^ "\n")
in
ListPair.appEq write_line (x, y);
TextIO.closeOut os
end;
Example usage
- val x = [1.0, 2.0, 3.0, 1e11];
val x = [1.0,2.0,3.0,100000000000.0] : real list
- val y = map Math.sqrt x;
val y = [1.0,1.41421356237,1.73205080757,316227.766017] : real list
- writeDat ("sqrt.dat", x, y, 3, 5);
val it = () : unit
- val is = TextIO.openIn "sqrt.dat";
val is = - : TextIO.instream
- print (TextIO.inputAll is);
1.0 1.0
2.0 1.4142
3.0 1.7321
1E11 3.1623E05
val it = () : unit
[edit] Tcl
set x {1 2 3 1e11}
foreach a $x {lappend y [expr {sqrt($a)}]}
set fh [open sqrt.dat w]
foreach a $x b $y {
puts $fh [format "%.*g\t%.*g" $xprecision $a $yprecision $b]
}
close $fh
set fh [open sqrt.dat]
puts [read $fh [file size sqrt.dat]]
close $fh
outputs
1 1 2 1.4142 3 1.7321 1e+011 3.1623e+005







