'''`[binary] format`''' Give each value the binary representation indicated in a specification and produce a string containing the concatenated results. ** Synopsis **http://here.com/what.html%|%link name%|% '''[binary format]''' ''formatString ?arg arg ...?'' ** See Also ** [binary]: [binary scan]: Extract values from a string according to the binary representations indicated in a pattern specification. [format]: Give each value the string representation specified in a template and interpolate that string representation into the template. [scan]: Extract values from a string according to the string representations indicated in a pattern specification. [Working with binary data]: ** Description ** ''formatString'' is a sequence of zero or more field specifiers separated by zero or more spaces. Each field specifier contains a single character to indicate an output format, followed by an optional numeric ''count''. Each field specifier that produces output consumes at least one argument. See [https://www.tcl.tk/man/tcl/TclCmd/binary.htm%|%the documentation] for a detailed description of the available field specifiers. ''count'' typically indicates how many items of the specified type are taken from the value. If present, the ''count'' is a non-negative decimal integer or `*`, which normally indicates that all of the items in the value are to be used. If the number of arguments does not match the number of fields in the format string that consume arguments, then an error is generated. Each remaining argument is given the binary representation indicated by the next field specifier in ''format String'' and concatenated to the result, which is returned at the end of the routine. ---- Here is a small example to clarify the relation between the field specifiers and the arguments: ====== binary format d3d {1.0 2.0 3.0 4.0} 0.1 ====== The first argument is a list of four numbers, but because of the count of 3 for the associated field specifier, only the first three will be used. The second argument is associated with the second field specifier. The resulting binary string contains the four numbers 1.0, 2.0, 3.0 and 0.1. Each type-count pair moves an imaginary cursor through the binary data, storing bytes at the current position and advancing the cursor to just after the last byte stored. The cursor is initially at position 0 at the beginning of the data. ---- [RJM] 2004-07-27: What about sending numeric expression results as binary representation to files or communication channels? It can be coded this way (example with one and two values to being sent): ====== puts $fid [binary format S1 [expr {...}]] puts $fid [binary format S2 "[expr {...}] [expr {...}]"] ====== Contrary to the simple case of ====== set a [expr {...}] ====== where no intermediate number<->string conversions takes place, since smart Tcl writes the real or int value result directly in '''a'''. However, conversion to binary output seems to involve string conversion ([expr] result) and then conversion to binary during [binary format] execution, as [time] investigations seem to confirm. `[binary scan]` does not necessarily have this superfluous string conversion, because the command provides a reference to a target variable and hence can handle the processing from source (binary) to target (binary representation) monolithically. Expert contributions very welcome! [BR]: See [Working with binary data] for a description how strings and binary data relate. There should be no visible conversions from the POV of Tcl scripts. [Lars H]: I'm hardly an expert, but aren't the arguments supposed to be ''lists''? The man page says (about the '''c''' format specifier) that : If no count is specified, then arg must consist of an integer value; otherwise arg must consist of a list containing at least count integer elements. (and '''S''' is described as being like '''s''', which is described as being like '''c'''). Thus it should be ====== puts $fid [binary format S [expr {...}]] puts $fid [binary format S1 [list [expr {...}]]] puts $fid [binary format S2 [list [expr {...}] [expr {...}]]] ====== [RJM] replies: thanks for pointing this out. Normally I don't use [list] when I'm sure that the elements contain no white spaces (readability...). But a short investigation showed me, that using list instead of ".."-grouping here executes faster! Apparently, a conversion from string to list is saved when a [pure list] is used. I also found another interesting page in the wiki concerning strings vs. lists. When I find it, I'll add a link here. Another note: binary format S indeed executes faster than binary format S1. But still outputting an expression result to a file (ascii string) is faster than outputting the binary representation of the [expr] result via [binary format], also when I use the "I" or "i" option (exact 32 bit native binary representation). ** Floating Point Numbers ** [Chad]: Why is it that after ====== binary scan [binary format f 393.84] f n ====== the value of n is 393.839996338? [AM] 2011-01-14: This is a classic problem: the decimal number 393.84 can not be represented exactly in the binary format that most contemporal computers use. The value you see is the closest binary value. Compare this to the difficulty of representing 1/3 in decimal numbers. [LV]: Are there any languages which provide an add-on module or mode of operation where '''real''' variables are represented in a programmatic form designed not to lose percision? I was thinking that perhaps [APL] or [LISP] was one such language. Perhaps someone has - or could - create a package for Tcl that would permit one to do math in that fashion for people who don't care about the lost computer cycles but do care about the precision. [CliC]: [http://racket-lang.org%|%Racket%|%], a Scheme dialect, has "rational" types, so that e.g., 1/3 may be used in calculations with no loss of precision. I'm not a heavy user of it, though. I just downloaded it to check out the authors' "modern answer to [SICP]" programming tutorial. <> Tcl syntax | Category Command | Category Binary Data | Category String Processing