How to configure Octave terminal to output numbers without scientific notation? - octave

I am trying to print a long table of numbers in octave terminal.
disp(vec);
What I get
7.0931e-01
6.2041e-05
9.7740e-01
9.9989e-01
8.8428e-01
9.0524e-01
...
Such numerical notation is a pain to read. How can I set octave terminal to output numbers normally as 0.7, 0.014, 0.95?

You can use format short g to display each number is a more logical format
format short g
disp(vec)
% 0.70931
% 6.2041e-05
% 0.9774
% 0.99989
% 0.88428
% 0.90524

Using 'fprintf' could help in such cases
a=0.0001234;
fprintf('%.3f\n',a)
But here the limitation is that number of decimal points would be fixed so in some numbers it will display zeros at the end while for some numbers it might cut off the number.

Related

force Octave to show only scientific notation

See this code below, from Octave's Command Prompt:
>> log( 0.1 ) * 5e-8
ans = -0.00000011513
As can be seen, there are quite a few zeros ( 6 to be exact). I would like if the number is displayed as 1.1513e-7. Or, scientific notation, by default. How does one do that?
You can change the format of the ouput displayed by octave with the function format,
e.g. format short e forces short length exponential notation, which seems that is what you want.

correct scientific notation on CSV import into MATLAB

I have a set of numerical data in a CSV file that is accompanied with a letter which denotes the mathematical notation for the associated number such as 'm' for milli, 'n' for nano.
for example
190.4 n
100.7 n
20.3 n
9.5 m
ect
Now when I import into MATLAB in a comma column delimiter in a numerical matrix, the scientific notation is dropped and the number is produced in a cell, unfortunately MATLAB has not taken into account the alphabetical notation and therefore the numerical data is erroneous.
Is there any way to allow the conversion into the full numerical value taking into account the notation?
Use the system command to shell out to the operating system and invoke awk or similar to make sense of and reformat your input data.
Something like this (untested)
awk '/m/ {print $1/1000}
/n/ {print $1/1000000000} ' stupid.csv > sensible.csv

tcl : manipulating numbers bigger than 0xFFFFFFFF with `format`

I need to do some operation on MAC addresses, coded on 48 bits, but format truncates the results :
format 0x%x 0x100000000 ;# --> 0x0
Is it possible to do something for this, or must I adapt my code to use smaller numbers ?
In Tcl 8.4 just give the size modifier l to the field specificator of format. This way, you tell format to interpret the value as (at least) 64-bit number (same size of wide(), which is machine dependent):
format 0x%lx 0x100000000
(Note that it is a lower case el letter, not the one digit.)
In Tcl 8.5 and later, integer math is done with arbitrary precision and the ll size modifier tells format to not truncate the value:
format 0x%llx 0x100000000
(Again, they are two lower case el letters, not two one digits.)

Is there a "native" way to convert from numbers to dB in Tcl

dB or decibel is a unit that is used to show ratio in logarithmic scale, and specifecly, the definition of dB that I'm interested in is X(dB) = 20log(x) where x is the "normal" value, and X(dB) is the value in dB. When wrote a code converted between mil. and mm, I noticed that if I use the direct approach, i.e., multiplying by the ratio between the units, I got small errors on the opposite conversion, i.e.: to_mil [to_mm val_in_mil] wasn't equal to val_in_mil and the same with mm. The library units has solved this problem, as the conversions done by it do not have that calculation error. But the specifically doesn't offer (or I didn't find) the option to convert a number to dB in the library.
Is there another library / command that can transform numbers to dB and dB to numbers without calculation errors?
I did an experiment with using the direct math conversion, and I what I got is:
>> set a 0.005
0.005
>> set b [expr {20*log10($a)}]
-46.0205999133
>> expr {pow(10,($b/20))}
0.00499999999999
It's all a matter of precision. We often tend to forget that floating point numbers are not real numbers (in the mathematical sense of ℝ).
How many decimal digit do you need?
If you, for example, would only need 5 decimal digits, rounding 0.00499999999999 will give you 0.00500 which is what you wanted.
Since rounding fp numbers is not an easy task and may generate even more troubles, you might just change the way you determine if two numbers are equal:
>> set a 0.005
0.005
>> set b [expr {20*log10($a)}]
-46.0205999133
>> set c [expr {pow(10,($b/20))}]
0.00499999999999
>> expr {abs($a - $c) < 1E-10}
1
>> expr {abs($a - $c) < 1E-20}
0
>> expr {$a - $c}
8.673617379884035e-19
The numbers in your examples can be considered "equal" up to an error or 10-18. Note that this is just a rough estimate, not a full solution.
If you're really dealing with problems that are sensitive to numerical errors propagation you might look deeper into "numerical analysis". The article What Every Computer Scientist Should Know About Floating-Point Arithmetic or, even better, this site: http://floating-point-gui.de might be a start.
In case you need a larger precision you should drop your "native" requirement.
You may use the BigFloat offered by tcllib (http://tcllib.sourceforge.net/doc/bigfloat.html or even use GMP (the GNU multiple precision arithmetic library) through ffidl (http://elf.org/ffidl). There's an interface already defined for it: gmp.tcl
With the way floating point numbers are stored, every log10(...) can't correspond to exactly one pow(10, ...). So you lose precision, just like the integer divisions 89/7 and 88/7 both are 12.
When you put a value into floating point format, you should forget the ability to know it's exact value anymore unless you keep the old, exact value too. If you want exactly 1/200, store it as the integer 1 and the integer 200. If you want exactly the ten-logarithm of 1/200, store it as 1, 200 and the info that a ten-logarithm has been done on it.
You can fill your entire memory with the first x decimal digits of the square root of 2, but it still won't be the square root of 2 you store.

round number to 2 decimal places

I need to round a number to two decimal places.
Right now the following rounds to the nearest integer I guess
puts [expr {round($total_rate)}]
If I do something like below it does not work. Is there another way around?
puts [expr {round($total_rate,2)}]
The simplest way to round to a specific number of decimal places is with format:
puts [format "%.2f" $total_rate]
Be aware that if you're using the rounded value for further calculations instead of display to users, most values that you print using rounding to X decimal places will not have an exact representation in binary arithmetic (which Tcl uses internally, like vast numbers of other programming languages). It's best to reserve rounding to a specific number of DPs to the point where you're showing values to people.
expr {double(round(100*$total_rate))/100}
example
% set total_rate 1.5678
1.5678
% expr {double(round(100*$total_rate))/100}
1.57
% set total_rate 1.4321
1.4321
% expr {double(round(100*$total_rate))/100}
1.43
puts [format "%.2f" $total_rate]
By using format, we can see the result in output but how to use the same value in the program, i.e., we can see 1.448 as 1.45 in the output but can we use 1.45 in the program then.
It is unclear whether the original question "I need to round a number" really was "I need to print out a rounded-off value of a number". The latter is really best answered with a [format ...], but the former could be interpreted as a need for a number of significant digits, i.e. how to adjust the number itself, and not just to format the printout string. I think the only answer that serves this purpose so far is the elegant one Donal Fellows has provided. However, for "significant digits" instead of "digits after the decimal" I think a small modification is in order: get the number to be between 1 and 10 first (or between 0.1 and 1, if that is your convention), then trim the number of digits after the decimal. Without that, something like roundto(0.00000001234567,4) will get you a zero.
proc tcl::mathfunc::roundto {value sigfigs} {
set pow [expr ($sigfigs-1)-floor(log10($value))]
expr {round(10**$pow*$value)/10.0**$pow}
}
expr roundto(0.000000123456789,5)
produces a value rounded off to 5 significant figures:
1.2346e-7