Join devRant
Do all the things like
++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatar
Sign Up
Pipeless API
From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple API
Learn More
Search - "floating point math"
-
POSTMORTEM
"4096 bit ~ 96 hours is what he said.
IDK why, but when he took the challenge, he posted that it'd take 36 hours"
As @cbsa wrote, and nitwhiz wrote "but the statement was that op's i3 did it in 11 hours. So there must be a result already, which can be verified?"
I added time because I was in the middle of a port involving ArbFloat so I could get arbitrary precision. I had a crude desmos graph doing projections on what I'd already factored in order to get an idea of how long it'd take to do larger
bit lengths
@p100sch speculated on the walked back time, and overstating the rig capabilities. Instead I spent a lot of time trying to get it 'just-so'.
Worse, because I had to resort to "Decimal" in python (and am currently experimenting with the same in Julia), both of which are immutable types, the GC was taking > 25% of the cpu time.
Performancewise, the numbers I cited in the actual thread, as of this time:
largest product factored was 32bit, 1855526741 * 2163967087, took 1116.111s in python.
Julia build used a slightly different method, & managed to factor a 27 bit number, 103147223 * 88789957 in 20.9s,
but this wasn't typical.
What surprised me was the variability. One bit length could take 100s or a couple thousand seconds even, and a product that was 1-2 bits longer could return a result in under a minute, sometimes in seconds.
This started cropping up, ironically, right after I posted the thread, whats a man to do?
So I started trying a bunch of things, some of which worked. Shameless as I am, I accepted the challenge. Things weren't perfect but it was going well enough. At that point I hadn't slept in 30~ hours so when I thought I had it I let it run and went to bed. 5 AM comes, I check the program. Still calculating, and way overshot. Fuuuuuuccc...
So here we are now and it's say to safe the worlds not gonna burn if I explain it seeing as it doesn't work, or at least only some of the time.
Others people, much smarter than me, mentioned it may be a means of finding more secure pairs, and maybe so, I'm not familiar enough to know.
For everyone that followed, commented, those who contributed, even the doubters who kept a sanity check on this without whom this would have been an even bigger embarassement, and the people with their pins and tactical dots, thanks.
So here it is.
A few assumptions first.
Assuming p = the product,
a = some prime,
b = another prime,
and r = a/b (where a is smaller than b)
w = 1/sqrt(p)
(also experimented with w = 1/sqrt(p)*2 but I kept overshooting my a very small margin)
x = a/p
y = b/p
1. for every two numbers, there is a ratio (r) that you can search for among the decimals, starting at 1.0, counting down. You can use this to find the original factors e.x. p*r=n, p/n=m (assuming the product has only two factors), instead of having to do a sieve.
2. You don't need the first number you find to be the precise value of a factor (we're doing floating point math), a large subset of decimal values for the value of a or b will naturally 'fall' into the value of a (or b) + some fractional number, which is lost. Some of you will object, "But if thats wrong, your result will be wrong!" but hear me out.
3. You round for the first factor 'found', and from there, you take the result and do p/a to get b. If 'a' is actually a factor of p, then mod(b, 1) == 0, and then naturally, a*b SHOULD equal p.
If not, you throw out both numbers, rinse and repeat.
Now I knew this this could be faster. Realized the finer the representation, the less important the fractional digits further right in the number were, it was just a matter of how much precision I could AFFORD to lose and still get an accurate result for r*p=a.
Fast forward, lot of experimentation, was hitting a lot of worst case time complexities, where the most significant digits had a bunch of zeroes in front of them so starting at 1.0 was a no go in many situations. Started looking and realized
I didn't NEED the ratio of a/b, I just needed the ratio of a to p.
Intuitively it made sense, but starting at 1.0 was blowing up the calculation time, and this made it so much worse.
I realized if I could start at r=1/sqrt(p) instead, and that because of certain properties, the fractional result of this, r, would ALWAYS be 1. close to one of the factors fractional value of n/p, and 2. it looked like it was guaranteed that r=1/sqrt(p) would ALWAYS be less than at least one of the primes, putting a bound on worst case.
The final result in executable pseudo code (python lol) looks something like the above variables plus
while w >= 0.0:
if (p / round(w*p)) % 1 == 0:
x = round(w*p)
y = p / round(w*p)
if x*y == p:
print("factors found!")
print(x)
print(y)
break
w = w + i
Still working but if anyone sees obvious problems I'd LOVE to hear about it.38 -
console.log(0.47-0.01===0.46);
Output: false :/
That got me stuck for quite a while..
Learned more about floating point arithmetic and representation 😊7 -
Apparently, floating point math is broken.
=SUM((2.1 - 2.0) - 0.1)
In PHP and Haskell this also happens10 -
Reading another rant about scrolling and decimal values I felt an urge to write about a bad practice I often see.
Load on demand when scrolling has been popular for quite some years but when implementing it, take some time to consider the pages overall layout.
I have several times encountered sites with this “helpful” feature that at the same time follows another staple feature of pages, especially news sites, of putting contact and address information in the footer ...
Genius right :)
I scroll down to find contact info and just as it comes in view new content gets loaded and pushes it out of view.
If you plan to use load on demand, make sure there is nothing below anyone will try to reach, no text or links or even pictures, you will frustrate the visitor ;)
The rant I was inspired by probably did not do this but its what got me thinking.
https://devrant.com/rants/1356907/...1 -
Inspired by @shahriyer 's rant about floating point math:
I had a bug related to this in JavaScript recently. I have an infinite scrolling table that I load data into once the user has scrolled to the bottom. For this I use scrollHeight, scrollTop, and clientHeight. I subtract scrollTop from scrollHeight and check to see if the result is equal to clientHeight. If it is, the user has hit the bottom of the scrolling area and I can load new data. Simple, right?
Well, one day about a week and a half ago, it stopped working for one of our product managers. He'd scroll and nothing would happen. It was so strange. I noticed everything looked a bit small on his screen in Chrome, so I had him hit Ctrl+0 to reset his zoom level and try again.
It. Fucking. Worked.
So we log what I dubbed The Dumbest Bug Ever™ and put it in the next sprint.
Middle of this week, I started looking into the code that handled the scrolling check. I logged to the console every variable associated with it every time a scroll event was fired. Then I zoomed out and did it.
Turns out, when you zoom, you're no longer 100% guaranteed to be working with integers. scrollTop was now a float, but clientHeight was still an integer, so the comparison was always false and no loading of new data ever occurred. I tried round, floor, and ceil on the result of scrollHeight - scrollTop, but it was still inconsistent.
The solution I used was to round the difference of scrollHeight - scrollTop _and_ clientHeight to the lowest 10 before comparing them, to ensure an accurate comparison.
Inspired by this rant: https://devrant.com/rants/1356488/...2 -
aaAAaaAaaAaaAaAAAAAaAaaa floating points!
I debugged my algorithm for quite a while, wondering why it sometimes gives out "Circle(Point({1.7976931348623157E308,1.7976931348623157E308}),1.7976931348623157E308)" as the smallest circle around a group of points.
Figured out that it sometimes just never found any circle defined by two or three of the points which included all points (which is mathematically impossible).
Then finally I made it print out the points it thought were not inside the circle:
"1,7,8: Circle(Point({0.6636411126185259,0.535709780023259}),0.4985310690982777)
skip, 1 not inside"
So it defined the circle with 1 being on the edge, but then thought 1 was outside. Thank you, floating point Math.
For anyone wondering about the notation: That way I can directly copy/paste it into Geogebra to have a visualisation.7 -
Question - is this meaningful or is this retarded?
if
2*3 = 6
2*2 = 4
2*1 = 2
2*0 = 0
2*-1 = -2
then why doesnt this work?
6/3 = 2
6/2 = 3
6/1 = 6
6/0 = 0
6/-1 = -6
if n/0 is forbidden and 1/n returns the inverse of n, why shouldn't zero be its own inverse?
If we're talking "0" as in an infinitely precise definition of zero, then 1/n (where n is arbitrarily close to 0), then the result is an arbitrarily large answer, close to infinite, because any floating point number beneath zero (like an infinitely precise approximation of zero) when inverted, produces a number equal to or greater than 1.
If the multiplicative identity, 1, covers the entire set of integers, then why shouldn't division by zero be the inverse of the multiplicative identity, excluding the entire set? It ONLY returns 0, while anything n*1 ONLY returns n.
This puts even the multiplicative identity in the set covered by its inverse.
Ergo, division by zero produces either 0 or infinity. When theres an infinity in an formula, it sometimes indicates theres been
some misunderstanding or the system isn't fully understood. The simpler approach here would be to say therefore the answer is
not infinity, but zero. Now 'simpler' doesn't always mean "correct", only more elegant.
But if we represent the result of a division as BOTH an integer and mantissa
component, e.x
1.234567 or 0.1234567,
i.e. a float, we can say the integer component is the quotient, and the mantissa
is the remainder.
Logically it makes sense then that division by zero is equivalent to taking the numerator, and leaving it "undistributed".
I.e. shunting it to the remainder, and leaving the quotient as zero.
If we treat this as equivalent of an inversion, we can effectively represent the quotient from denominators of n/0 as 1/n
Meaning even 1/0 has a representation, it just happens to be 0.000...
Therefore
(n * (n/0)) = 1
the multiplicative identity
because
(n* (n/0)) == (n * ( 1/n ))
People who math. Is this a yea or nay in your book?25 -
can we just get rid of floating points? or at least make it quite clear that they are almost certainly not to be used.
yes, they have some interesting properties that make them good for special tasks like raytracing and very special forms of math. but for most stuff, storing as much smaller increments and dividing at the end (ie. don't store money as 23.45. store as 2,345. the math is the same. implement display logic when showing it.) works for almost all tasks.
floating point math is broken! and most people who really, truely actually need it can explain why, which bits do what, and how to avoid rounding errors or why they are not significant to their task.
or better yet can we design a standard complex number system to handle repeating divisions and then it won't be an issue?
footnote: (I may not be perfectly accurate here. please correct if you know more)
much like 1/3 (0.3333333...) in base 10 repeats forever, that happens with 0.1 in base 2 because of how floats store things.
this, among other reasons, is why 0.1+0.2 returns 0.300000046 -
So the project I work on basically has to talk to a 3rd party plugin, through a 3rd party framework. The 3rd party plugin is a black box. This conversation happened:
Software guy: so we aren't sure what is breaking the thing. It's either us or the plugin, but it's probably both.
Systems guy: well then if we aren't sure then why are we writing an issue for it.
SWG: because we aren't sure but we know we are doing at least something that contributes. We read int X from a table and put it into a float. X doesn't perfectly represent in a float. It comes out X.0001. Then they take it and when it comes back it comes back as Y.0001. We cram it into an int so it becomes Y, we compare it to X which is really X.0001 and it comes back invalid.
SG: well as long as we are sending them the right number . . .
SWG: but we aren't sending them the right number. They are expecting X not X.0001. Then they send us back Y.0001 but it should be X so it's wrong.
SG: so they're giving us the wrong return value.
SWG: yes, but because we're giving them the wrong number.
SG: well not exactly . . .
SWG: yes exactly. It is off by .0001 because of floating point math.
SG: well . . .
Me: look it doesn't matter how it's breaking. But it IS broken. Which is why we're filling out the damn problem report. THEY ARE EDITABLE. We talked to the customer and gave them the risk assessment. They don't care. It happens rarely any way.
SG: then can we lower the severity?
Me: no. Severity doesn't relate to risk. That is a whole different process. Severity assumes it has already happened. It's a a high severity.
SG: but the metrics.
Me: WE GIVE THE METRICS TO THE CUSTOMER. WE TALKED TO THE CUSTOMER. THEY DON'T GIVE A SHIT.
And that was how I spent Wednesday wondering how a level 4 lead systems engineer got his job. How many push ups did he do? What kind of juice did he drink?2 -
if((fabs(a - 0.0) > 0.00001) ||
(fabs(b - 0.0) > 0.00001) ||
(fabs(c - 0.0) > 0.00001))
What have you seen dear traveller? What have you seen?2 -
Our systems lead is trying to tell our software person how much adding unit tests would cost. It also sounds like he wants TDD to be added in after the fact. And he's bitching because the software guy won't move forward with it until we get it with the customer. He also wants all of them automated, but doesn't want to accept that that is going to cost a lot. Like a lot, a lot. This is a guy who doesn't know algorithms (had to explain dykstra to him), doesn't understand the tech stack we are using (I had to explain .net versions, the JIT compiler, and garbage collection to him), and seems not to understand hardware (I had to explain floating point math to him), yet he feels qualified to tell us how long it is going to take us to implement automated unit tests for major, complex features.
-
current language vba.
(14 / 24) - (8 / 24) > (6 / 24)
compiled to true. apparently rounding to 8 digits did the trick. quirky was that debug.printing each calculations showed exactly '0.25' for both not giving a hint about some float issue in the first place. ah, and rounding to 4 digits wasn't right either. -
floating point numbers are workarounds for infinite problems people didn’t find solution yet
if you eat a cake there is no cake, same if you grab a piece of cake, there is no 3/4 cake left there is something else yet to simplify the meaning of the world so we can communicate cause we’re all dumb fucks who can’t remember more than 20000 words we named different things as same things but in less amount, floating point numbers were a biggest step towards modern world we even don’t remember it
we use infinity everyday yet we don’t know infinite, we only partially know concept of null
you say piece of cake but piece is not measurement - piece is infinite subjective amount of something
everything that is subjective is infinite, like you say a sentence it have infinite number of meanings, you publish a photo or draw a paining there are infinite number of interpretations
you can say there is no cake but isn’t it ? you just said cake so your mind want to materialize something you already know and since you know the cake word there is a cake cause it’s infinite once created
if you think really hard and try to get that feeling, the taste of your last delicious cake you can almost feel it on your tongue cause you’re connected to every cake taste you ate
someone created cake and once people know what cake is it’s infinite in that collection, but what if no one created cake or everyone that remember how cake looks like died, everything what’s cake made of extinct ? does it exist or is it null ? that’s determinism and entropy problem we don’t understand, we don’t understand past and future cause we don’t understand infinity and null, we just replaced it with time
there is no time and you can have a couple of minutes break are best explanations of how null and infinite works in a concept of time
so if you want to change the world, find another thing that explains infinity and null and you will push our civilization forward, you don’t need to know any physics or math, you just need to observe the world and spot patterns10 -
Why do we still use floating-point numbers? Why not use fixed-point?
Floating-point has precision errors, and for some reason each language has a different level of error, despite all running on the same processor.
Fixed-point numbers don't have precision issues (unless you get way too big, but then you have another problem), and while they might be a bit slower, I don't think there is enough of a difference in speed to justify the (imho) stupid, continued use of floating-point numbers.
Did you know some (low power) processors don't have a floating-point processor? That effectively makes it pointless to use floating-point, it offers no advantage over fixed-point.
Please, use a type like Decimal, or suggest that your language of choice adds support for it, if it doesn't yet.
There's no need to suffer from floating-point accuracy issues.26