![]() |
Forum Index : Microcontroller and PC projects : a small oddity in cint() and hex$
![]() ![]() ![]() ![]() |
|||||
Author | Message | ||||
robert.rozee Guru ![]() Joined: 31/12/2012 Location: New ZealandPosts: 2428 |
can you extend it up past that range, up to say 16777220? cheers, rob :-) |
||||
zeitfest Guru ![]() Joined: 31/07/2019 Location: AustraliaPosts: 570 |
Not with 32 bit. I am wondering about that situation. I tend to think, a system should prevent an integer being generated if it will express more precision than the original data (float) can provide, or flag it somehow. My distant memories of the pic processors recall some arithmetic flags in the status registers (?) for those things (?). |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4032 |
It gets awkward, because the obvious FOR loop (adding 1 on each loop and testing for the limit) loops forever. That's because adding 1 actually adds zero now that you've hit the max. If you just assign a constant then you rely on what the compiler/code generator turns that into. I see: trying to use 16777217 actually uses 16777216 trying to use 16777218 actually uses 16777218 trying to use 16777219 actually uses 16777220 (they carry on in steps of 2) The -ves are the same (with minus sign). This is C and it has fairly well defined behaviour (hampered by the fact floating point is what it is). John Edited 2020-05-15 16:41 by JohnS |
||||
robert.rozee Guru ![]() Joined: 31/12/2012 Location: New ZealandPosts: 2428 |
changing both occurrences of this line: DO WHILE ( i < 4 ) to this: DO WHILE ( i < 12 ) will achieve the desired result; based upon the result i can deduce what is most likely to be happening. cheers, rob :-) |
||||
zeitfest Guru ![]() Joined: 31/07/2019 Location: AustraliaPosts: 570 |
What does MMBasic do up to say 16777220? I am a bit surprised the Pascal jumped the 09 figure. I am wondering if the different sources of C libraries show a difference. My (old) ANSI C book does not define the behaviour in that situation, probably IEEE does (?) In general using single precision to yield the larger range of integers would be regarded as an unfavorable design, even if C lets it happen. Using double precision works (f77/C), I did not build in a trap for the single-precision use outside its bounds, it was intended but I lost interest PROGRAM z C DOUBLE x ... ... 16777214.00000000 16777214 16777215.00000000 16777215 16777216.00000000 16777216 16777217.00000000 16777217 16777218.00000000 16777218 16777219.00000000 16777219 16777220.00000000 16777220 16777221.00000000 16777221 16777222.00000000 16777222 -16777214.00000000 -16777214 -16777215.00000000 -16777215 -16777216.00000000 -16777216 -16777217.00000000 -16777217 -16777218.00000000 -16777218 -16777219.00000000 -16777219 -16777220.00000000 -16777220 -16777221.00000000 -16777221 -16777222.00000000 -16777222 |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4032 |
C does what you'd expect, if you think it through. It can easily handle the range but not the precision. So as you increase the magnitude more and more it does the right thing - approximates. (Internally, as you go past the range which can be represented the exponent is altered by one, effectively shifting the mantissa right by one bit, and that's why half the numbers in the new part of the range get rounded/truncated - what would have been the bottom bit in the mantissa gets lost as there's no room for it.) The same would happen with a double precision, just a much bigger range. I don't have a C standard conveniently to hand but you can be sure this is defined behaviour. Note that we're not doing anything that ought to cause an error (e.g. we're not causing overflow) - in any floating point system as far as I know, and not in IEEE 754 I am fairly sure but it's not the most easily grasped standard. John Edited 2020-05-16 00:06 by JohnS |
||||
robert.rozee Guru ![]() Joined: 31/12/2012 Location: New ZealandPosts: 2428 |
i probably wasn't clear enough. please try with the following lines: REAL x and DO WHILE ( i < 12 ) as it stands, running on an MX170, MMbasic does a double-step from 0x800001 up to 0xFFFFFF, and for values beyond this stops stepping. with the proposed change, it should produce the correct results up to 0xFFFFFF, and from 0x1000000 stop stepping - adding 1 will produce no increment as 1 is below the level of granularity. i've just checked this behaviour with fpc (pascal). cheers, rob :-) Edited 2020-05-16 00:40 by robert.rozee |
||||
zeitfest Guru ![]() Joined: 31/07/2019 Location: AustraliaPosts: 570 |
It is as you suggest, adding 1 after the 16777216 produces no increment, adding 2 increments ok, presumably until the next watershed etc 16777214.000000 16777214 16777215.000000 16777215 16777216.000000 16777216 16777216.000000 16777216 16777216.000000 16777216 ... We are in good company .. java .. public class Main { public static void main(String[] args) { float fval = 16777217.0f ; int val ; val = (int) fval ; System.out.println(val); } } 16777216 although if I don't force the float it does gripe (ed) as it uses double and tries to then convert .. public class Main { public static void main(String[] args) { float fval = 16777215.0 ; int val ; val = (int) fval ; System.out.println(val); } } Main.java:8: error: incompatible types: possible lossy conversion from double to float float fval = 16777215.0 ; I am wondering what say C on raspberry pi does. Edited 2020-05-16 13:26 by zeitfest |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4032 |
It'll depend on the code and which compiler warnings are enabled. As I just wanted to find the range I used straightforward code and didn't bother with warnings. Essentially, float f; ... f = 16777216.0f; then print f. The above pretty much prevents warnings as I've told the compiler to assign a float to a float. I can mess about leaving off the trailing f (thus getting a double) and enabling warnings but TBH I can't see why because if writing numerically important code you have to understand this stuff and do proper error analysis. John Edited 2020-05-16 16:22 by JohnS |
||||
zeitfest Guru ![]() Joined: 31/07/2019 Location: AustraliaPosts: 570 |
I am relieved my little f77 interpreter handles it OK. Shepherding half-a-dozen or so datatypes through parsing via a shunting-yard treatment and calculation etc while retaining canonical accuracy is not code I want to revisit !! At one stage I could set it to reject any math that tried to mix 32 bit and 64 bit floating point....that was just too exasperating to be practical. But it raises a question, ie, if hardware A is always 32 bit and hardware B is always 64 bit, and the interpreter/language used is arbitrarily handling values as integers or floating point, I think the same user code may run differently on the two platforms eg if a floating point value is compared to an integer and so on. (?) |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4032 |
I suspect f77 will in effect say (C does), because ANSI/ISO standards tend to cover such things and have done for decades. Yes code can behave differently if it fails to be written with the behaviours of floating point in mind. (This isn't an issue for most software, in reality.) I suspect your specific example is not allowed, but your general point is true :) (C specifies in probably more detail than most ever want to read what happens in many (I hope all) of the awkward cases. It's not particularly easy to write 100% correct code using floating point, but the hardware does what the hardware does and all the software can do is its best despite that.) Things were much more painful when machine A had 6-bit characters (inevitably not ASCII), 24-bit integers, 48-bit floating point, and machine B had 8-bit characters, 60-bit floating point and I can't recall what size integers were. Oh, and machine C had 8-bit chars using EBCDIC, 32-bit integers, and so on. It didn't help that some were little endian, some big endian and the occasional (but common) were mixed endian... John |
||||
panky![]() Guru ![]() Joined: 02/10/2012 Location: AustraliaPosts: 1114 |
I am following this thread with interest but am struggling to understand the actual detail of the issue under discussion. Would it be possible to distill the main thrust down into simple language for those of us who are interested (and fascinated by the deep knowledge of those posting)? I really enjoy these semi theoretical discussions, thanks. Doug. ... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it! |
||||
Chopperp![]() Guru ![]() Joined: 03/01/2018 Location: AustraliaPosts: 1094 |
I'm with Doug.... ChopperP |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6266 |
I posted a reply but something happened so here it is again: Floating point numbers always seem to cause much discussion. The only way we can represent really big numbers with 32 bits is to round them off once they get too many digits. Later 'mites use 64bit floating point so we can have a lot more cash in the bank before the accounts don't balance. With 32bit floating point the rounding occurs at 2^24 or 16,777,216 To test the device I am programming on I use this one liner: x! = 50000000000 : if (x! = 50000000001)then print "Single" else print "Double"\n If X = X+1 we know we have a problem, but only if we expect ridiculous precision. Rob noticed that the precision dropped of on micromites at 2^23 or 8,388,608 and decided to dig around and find out why. He succeeded and MMBasic will be better for it. Jim VK7JH MMedit |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4032 |
In short, MMBasic (some/all versions) have one or more bugs. The computer can cope with all the integers (whole numbers) in the inclusive range -16777216 to 16777216 but MMBasic fails for some of them (a currently unknown number of them, I think). It appears to depend on which function or operation your code does. E.g. perhaps CINT, STR$ but I don't know which. I expect arithmetic operations (+ - * /) work fine, not sure about conversions. edit: although it needs fixing, all that happens looks to be a slight loss of precision (in floating point only, and in certain numbers) and that is very unlikely to affect MMBasic programs generally. John Edited 2020-05-18 17:14 by JohnS |
||||
zeitfest Guru ![]() Joined: 31/07/2019 Location: AustraliaPosts: 570 |
I think those are reasonable ways of describing it. However I would add add a caveat, ie if a problem like that surfaces it implies breadth-of-system accuracy programming and testing has been incomplete or failed, over several versions. If there is even a trivial difference (ed -in results) between the Extreme and CMM2, there is not supposed to be. These things are not a walk in the park. Commiserations guys.. a real slog I know. (exit thread) Edited 2020-05-20 05:42 by zeitfest |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4032 |
I'm not sure I understood that! Obviously, Rob's found a bug. But it probably affects no actual programs (other than whatever Rob was doing). Regardless of this bug, using any floating point generally means you're happy with slight inaccuracy - it certainly needs to mean that! - and have figured out any awkward cases where it could bite you. It also needs to mean you have figured that out! All this bug does is make that marginally more important, as it causes a slight loss of precision in cases where it should not cause such slight loss. John |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
happy? Not really. Stuck with it? undoubtedly I couldn't write a universal system that would deal with it all. I have written systems to specifically avoid problems like this but they all have ceilings. Damn you universe! ![]() ![]() Often times, the rounding errors are a product of the radix (base number) used - I had a discussion a few years back with someone that mathematically "proved" 9.99999... was equal to 10. I vaguely remember a maths teacher doing the same to show 1=2 or something like that. I tried to point out that it all depends on the radix and illustrated with 10/3 not possible to do precisely in radix 10, but perfect in radix 30... it was lost and degenerated into ad-hominem abuse from which I retired. |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4032 |
This bug is fixable, but may well be extremely low priority as it perhaps affects no actual programs? One for Geoff. (The issues with floating point can only be fully fixed by not using it. Otherwise just write code that copes.) John |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
just to qualify, having read my post back, when I said "stuck with it" I was referring to the inadequacies of our number systems, not any bug in the firmware ![]() |
||||
![]() ![]() ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |