There are many answers on how to separate fractional part from integer part in float, but is there a way to efficiently assemble float from 2 integer numbers? For example, 123 and 012345 will produce 123.012345 (doesn't have to be exact)
This question was after reading "How to parse space-separated floats in c++ quickly" where the linked answer uses the following approach to assemble floats:
using strtol extract number from left of the '.' (will be the integer), extract the number on the right of the '.' (will be the fractional part)
using the length of second number, multiply the number by 0.1, 0.01, 0.001, 0.0001 depending on its length
add left to right.
Is there a more efficient approach (in c++ 14 and above)? Currently it requires multiplication and addition, which can play role when assembling hundreds of millions of such numbers.
... Something that would set exponent and mantissa directly?
Edit:
regarding distinguishing 012345 from 12345 when it's in the int form, the author of the above link used strtol, so I can compute the length we travelled while parsing. So I would know that the number is 6 digits long (for example), even though I got 12345
Related
A simple question that turned out to be quite complex:
How do I turn a float to a String in GForth? The desired behavior would look something like this:
1.2345e fToString \ takes 1.2345e from the float stack and pushes (addr n) onto the data stack
After a lot of digging, one of my colleagues found it:
f>str-rdp ( rf +nr +nd +np -- c-addr nr )
https://www.complang.tuwien.ac.at/forth/gforth/Docs-html-history/0.6.2/Formatted-numeric-output.html
Convert rf into a string at c-addr nr. The conversion rules and the
meanings of nr +nd np are the same as for f.rdp.
And from f.rdp:
f.rdp ( rf +nr +nd +np – )
https://www.complang.tuwien.ac.at/forth/gforth/Docs-html/Simple-numeric-output.html
Print float rf formatted. The total width of the output is nr. For
fixed-point notation, the number of digits after the decimal point is
+nd and the minimum number of significant digits is np. Set-precision has no effect on f.rdp. Fixed-point notation is used if the number of
siginicant digits would be at least np and if the number of digits
before the decimal point would fit. If fixed-point notation is not
used, exponential notation is used, and if that does not fit,
asterisks are printed. We recommend using nr>=7 to avoid the risk of
numbers not fitting at all. We recommend nr>=np+5 to avoid cases where
f.rdp switches to exponential notation because fixed-point notation
would have too few significant digits, yet exponential notation offers
fewer significant digits. We recommend nr>=nd+2, if you want to have
fixed-point notation for some numbers. We recommend np>nr, if you want
to have exponential notation for all numbers.
In humanly readable terms, these functions require a number on the float-stack and three numbers on the data stack.
The first number-parameter tells it how long the string should be, the second one how many decimals you would like and the third tells it the minimum number of decimals (which roughly translates to precision). A lot of implicit math is performed to determine the final String format that is produced, so some tinkering is almost required to make it behave the way you want.
Testing it out (we don't want to rebuild f., but to produce a format that will be accepted as floating-point number by forth to EVALUATE it again, so the 1.2345E0 notation is on purpose):
PI 18 17 17 f>str-rdp type \ 3.14159265358979E0 ok
PI 18 17 17 f.rdp \ 3.14159265358979E0 ok
PI f. \ 3.14159265358979 ok
I couldn't find the exact word for this, so I looked into Gforth sources.
Apparently, you could go with represent word that prints the most significant numbers into supplied buffer, but that's not exactly the final output. represent returns validity and sign flags, as well as the position of decimal point. That word then is used in all variants of floating point printing words (f., fp. fe.).
Probably the easiest way would be to substitute emit with your word (emit is a deferred word), saving data where you need it, use one of available floating pint printing words, and then restoring emit back to original value.
I'd like to hear the preferred solution too...
I want to convert a double to a string and only display needed decimals.
So I cannot use
d := 123.4
s := Format('%.2f', [d]);
As it display as the result is 123.40 when I want 123.4.
Here is a table of samples and expected result
|Double|Result as string|
-------------------------
|5 |5 |
|5.1 |5.1 |
|5.12 |5.12 |
|5.123 |5.123 |
You can use the %g format string:
General: The argument must be a floating-point value. The value is converted to the shortest possible decimal string using fixed or
scientific format. The number of significant digits in the resulting
string is given by the precision specifier in the format string; a
default precision of 15 is assumed if no precision specifier is
present. Trailing zeros are removed from the resulting string, and a
decimal point appears only if necessary. The resulting string uses the
fixed-point format if the number of digits to the left of the decimal
point in the value is less than or equal to the specified precision,
and if the value is greater than or equal to 0.00001. Otherwise the
resulting string uses scientific format.
This is not as simple as you think. It all boils down to representability.
Let's consider a simple example of 0.1. That value is not exactly representable in double. This is because double is a binary representation rather than a decimal representation.
A double value is stored in the form s*2^e, where s and e are the significand and exponent respectively, both integers.
Back to 0.1. That value cannot be exactly represented as a binary floating point value. No combination of significand and exponent exist that represent it. Instead the closest representable value will be used:
0.10000 00000 00000 00555 11151 23125 78270 21181 58340 45410 15625
If this comes as a shock I suggest the following references:
Is floating point math broken?
http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html
http://floating-point-gui.de/
So, what to do? An obvious option is to switch to a decimal rather than binary representation. In Delphi that typically means using the Currency type. Depending on your application that might be a good choice, or it might be a terrible choice. If you wish to perform scientific or engineering calculations efficiently, for instance, then a decimal type is not appropriate.
Another option would be to look at how Python handles this. The repr function is meant, where possible, to yield a string with the property that eval(repr(x)) == x. In older versions of Python repr produced very long strings of the form 1.1000000000000001 when in fact 1.1 would suffice. Python adopted an algorithm that finds the shortest decimal expression that represents the floating point value. You could adopt the same approach. The snag is that the algorithm is very complex.
Right now I have made my own funcs to do bitwise and + not but then I saw the bit library and tried to use it but it doesn't work how I imagined, it returns a large decimal instead of the binary bit and so my question is actually a few.
First: how to do bitwise AND on binary number using the bit32 library.
10110111
11000100 = 10000100
Second: How to calculate the ipv4 broadcast address by adding the network address and the wildcard mask in binary form using the bit32 library
192.168.1.0 + 31 = 192.168.1.31
11000000.10100000.00000001.00000000
00000000.00000000.00000000.00011111 = 11000000.10100000.00000001.00011111
I am assuming that your bitwise and / not functions take string arguments.
Numbers can be represented in multiple ways.
The number 110101, which is in base two, has the same value as 53, which is in base 10.
When you say
x=123
Lua converts 123 into its binary representation, 1111011, which it then stores in memory as bits.
When you say
print(x)
Lua goes into memory, grabs x, which is 1111011, and then converts it into its more human-readable base 10 representation, and you see
123
The bitwise functions you wrote performs bit operations on strings which display the binary representation of a number like "1111011". the bit32 library performs bit operations on numbers, which display the decimal representation of a number like 123.
In Lua, "1001001" is a string, but if arithmatic operations are performed on it, it treats it as if it were a number written in base 10. So when you do
bit32.band("101","110")
the bit32.band function interprets its arguments as one-hundred-one and one-hundred-ten.
You must first convert your binary strings into numbers:
bit32.band(tonumber("101",2), tonumber("110",2))
How do you determine how many bits per character are required for a fixed length code in a string using huffman? i had an idea that you count the number of different characters in a string than you present that number in binary so that will be the fixed length but it doesn't work. For example in the string "letty lotto likes lots of lolly"...there are 10 different characters excluding the quotes(since 10 = 0101(4bits), i thought it meant all the characters can be represented using 4 bits), now the frequency of f is 1 and is encoded as 11111(5 bits)not 4.
Let's say you have a string with 50 "A"s, 35 "B"s and 15 "C"s.
With a fixed-length encoding, you could represent each character in that string using 2 bits. There are 100 total characters, so when using this method, the compressed string would be 200 bits long.
Alternatively, you could use a variable-length encoding scheme. If you allow the characters to have a variable number of bits, you could represent "A" with 1 bit ("0"), "B" with 2 bits ("10") and "C" with 2 bits ("11"). With this method, the compressed string is 150 bits long, because the most common pieces of information in the string take fewer bits to represent.
Huffman coding specifically refers to a method of building a variable-length encoding scheme, using the number of occurrences of each character to do so.
The fixed-length algorithm you're describing is entirely separate from Huffman coding. If your goal is to compress text using a fixed-length code, then your method of figuring out how many bits to represent each character with will work.
Given a double value like 1.00500000274996E-8, how do I convert it to it's non scientific format with a maximum number of digits after the decimal point - in this case with 8 digits it would be 1.00500000?
The conversion should not pad with zeros, so 2007 would come out as 2007, and 2012.33 and 2012.33.
I've tried lots of combinations using Format, FormatFloat, FloatToStrF but can't quite seem to hit the jackpot. Many thanks for any help.
Edit: I should clarify that I am trying to convert it to a string representation, without the Exponent (E) part.
FormatFloat('0.######################', 1.00500000274996E-8) should do the trick.
Output is: 0,0000000100500000274996
It will not output more digits than absolutely necessary.
See John Herbster's Exact Float to String Routines in CodeCentral. Perhaps not exactly what youre after but might be good starting point... CC item's description:
This module includes
(a) functions for converting a floating binary point number to its *exact* decimal representation in an AnsiString;
(b) functions for parsing the floating point types into sign, exponent, and mantissa; and
(c) function for analyzing a extended float number into its type (zero, normal, infinity, etc.)
Its intended use is for trouble shooting problems with floating point numbers.
His DecimalRounding routines might be of intrest too.