Write float arrays to a text file: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
(→‎{{header|PL/I}}: Added PureBasic)
Line 505: Line 505:
x(2), e(20, y_precision) );
x(2), e(20, y_precision) );
</lang>
</lang>
=={{header|PureBasic}}==
<lang 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</lang>
Text file output:
<pre>1.000 1.00000
2.000 1.41421
3.000 1.73205
99999997952.000 316227.75000</pre>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 18:08, 29 May 2010

Task
Write float arrays to a text file
You are encouraged to solve this task according to the task description, using any language you may 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.

Ada

<lang 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;</lang>

ALGOL 68

<lang algol68>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)

);</lang> Example usage: <lang algol68>[]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</lang> Output: <lang algol68>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</lang>

AWK

As usual, the order of array traversal in AWK is not necessarily the same as the input had: <lang awk>$ 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</lang>

For the text file part of the task, just redirect stdout to it.

C

<lang c>#include <stdio.h>

  1. 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;

}</lang>

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

c99 version

<lang c>/** gcc -Wall -std=c99 *.c -o a && a */

  1. include <limits.h> // LINE_MAX, see http://www.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
  2. ifndef LINE_MAX
  3. define LINE_MAX 2048
  4. endif
  5. include <math.h>
  6. include <stdio.h>
  7. 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;

}</lang> It prints:

1	1
2	1.4142
3	1.7321
1e+011	3.1623e+005

C++

Function writedat(): <lang cpp>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';

}</lang> Example: <lang cpp>#include <algorithm>

  1. include <cmath> // ::sqrt()
  2. include <fstream>
  3. include <iomanip> // setprecision()
  4. include <iostream>
  5. include <string>
  6. 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;

}</lang> Result:

1       1
2       1.4142
3       1.7321
1e+11   3.1623e+05

Common Lisp

<lang 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)))</lang>

Using CLISP I get

1.          1.0000
2.          1.4142
3.          1.7321
1.0E+011    3.16228E+5

D

<lang 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);

}</lang> output is: 1 1 2 1.4142 3 1.7321 1e+11 3.1623e+05

Fortran

In ANSI FORTRAN 77 or later use OPEN STATEMENT, and formatted WRITE statement with implied DO loop: <lang fortran> 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</lang>
Works with: Fortran version 90 and later

<lang fortran>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</lang>

The arrays x and y should have same bounds (and size); this constraint is not checked.

Haskell

Probably not very idiomatic but oh well <lang haskell>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</lang>

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

HicEst

<lang 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 </lang> 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: <lang HicEst>DLG(Text=x, Format='i12', Edit=y, Format='F10.2', Y=0)</lang>

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:

<lang idl>1 1 2 1.4142 3 1.7321 1E+011 3.1623E+005</lang>

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.

J

<lang 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</lang>

Java

<lang java5>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) { }
   }

}</lang>

OCaml

<lang 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</lang>

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 = ()

Perl

<lang 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);</lang> File contents

1	1
2	1.4142
3	1.7321
1e+11	3.1623e+05

PL/I

<lang 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) );

</lang>

PureBasic

<lang 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</lang> Text file output:

1.000	1.00000
2.000	1.41421
3.000	1.73205
99999997952.000	316227.75000

Python

Works with: Python version 2.6

<lang python>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)</lang>

Example usage <lang python>>>> 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</lang>

Works with: Python version 3

<lang python>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)</lang>

R

<lang 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)</lang>

Ruby

<lang ruby># prepare test data x = [1, 2, 3, 1e11] y = x.collect { |xx| Math.sqrt xx } xprecision = 3 yprecision = 5

  1. 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

  1. print the result file

open('sqrt.dat', 'r') { |f| puts f.read }</lang> Result:

1       1
2       1.4142
3       1.7321
1e+11   3.1623e+05

Standard ML

<lang sml>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;</lang> 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

Tcl

<lang 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</lang> outputs

1	1
2	1.4142
3	1.7321
1e+011	3.1623e+005