Reputation: 694
The 0x3f800000 represents 1.0 in single precision floating maths. I tried this but could not get the correct result from the program:
set x 0x3f800000
set y [expr double($x)]
puts $y
I just want to "cast" the value of x into a float so it will print on screen as float. How do I do this in tcl?
Please note that in the original problem that I am trying to solve, a tcl script reads value from a hardware register in Quartus II System Console debug system. However, I have given a simple example code to make it easy for others to understand what I need to do.
Upvotes: 0
Views: 561
Reputation: 4813
You can obtain the floating point value by converting the integer to a 4-byte binary string and then converting the binary string to a float:
set x 0x3f800000
binary scan [binary format i $x] f y
puts $y
Upvotes: 4
Reputation: 247022
There's nothing builtin for that. But some time at https://en.wikipedia.org/wiki/Single-precision_floating-point_format led me to:
proc binary32_to_double {value} {
set sign [expr {($value & 0b10000000000000000000000000000000) >> 31}]
set exp [expr {($value & 0b01111111100000000000000000000000) >> 23}]
set frac [expr {($value & 0b00000000011111111111111111111111) >> 0}]
set frac_bits [format {%023b} $frac]
set fraction 1.0
for {set i 1} {$i <= 23} {incr i} {
set bit [string range $frac_bits $i-1 $i-1]
set fraction [expr {$fraction + $bit * 2**double(-$i)}]
}
expr {(-1)**$sign * 2**double($exp - 127) * $fraction}
}
And demonstrating:
% binary32_to_double 0x3f800000
1.0
% binary32_to_double 0b00111110001000000000000000000000
0.15625
% binary32_to_double 0b10111110001000000000000000000000
-0.15625
And we can turn that an expr
function like this:
proc ::tcl::mathfunc::binary32 {value} {
binary32_to_double $value
# or, put that proc body here
}
So that:
set x 0x3f800000
set y [expr {binary32($x)}] ;# => 1.0
set x 0b00111110001000000000000000000000
set y [expr {binary32($x)}] ;# => 0.15625
Upvotes: 1