Write float arrays to a text file
From Rosetta Code
You are encouraged to solve this task according to the task description, using any language you may know.
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
Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
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: #
test:(
[]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] HicEst
REAL :: n=4, x(n), y(n)
CHARACTER :: outP = "Test.txt"
OPEN(FIle = outP)
x = (1, 2, 3, 1E11)
y = x ^ 0.5
DO i = 1, n
WRITE(FIle=outP, Format='F5, F10.3') x(i), y(i)
ENDDO
Alternative: Display or Edit the formatted arrays in a spreadsheet-like dialog with a common scroll bar. The menu More - Export - File writes the formatted arrays to a file:
DLG(Text=x, Format='i12', Edit=y, Format='F10.2', Y=0)
[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] PicoLisp
An exponential format like "1e11" is not supported
(setq *Xprecision 3 *Yprecision 5)
(scl 7)
(mapc
'((X Y)
(prinl
(round X *Xprecision)
" "
(round Y *Yprecision) ) )
(1.0 2.0 3.0)
(1.0 1.414213562 1.732050807) )
Output:
1.000 1.00000 2.000 1.41421 3.000 1.73205
[edit] PureBasic
#Size = 4
DataSection
Data.f 1, 2, 3, 1e11 ;x values, how many values needed is determined by #Size
EndDataSection
Dim x.f(#Size - 1)
Dim y.f(#Size - 1)
Define i
For i = 0 To #Size - 1
Read.f x(i)
y(i) = Sqr(x(i))
Next
Define file$, fileID, xprecision = 3, yprecision = 5, output$
file$ = SaveFileRequester("Text file for float data", "xydata.txt","Text file | *.txt", 0)
If file$
fileID = OpenFile(#PB_Any, file$)
If fileID
For i = 0 To #Size - 1
output$ = StrF(x(i), xprecision) + Chr(9) + StrF(y(i), yprecision)
WriteStringN(fileID, output$)
Next
CloseFile(fileID)
EndIf
EndIf
Text file output:
1.000 1.00000 2.000 1.41421 3.000 1.73205 99999997952.000 316227.75000
[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

