Comments (21)
Thanks for the feedback so far, I will have to take some time to analyse it with the team now. Merci.
from math.
it's probably up to us to manipulate it.
It probably is indeed. But it shouldn't be that hard: just add 2^(number of bits)
if you get a negative result:
-8 + (2 ^ 16) = 65528
from math.
Hi, good point, not
was omitted in #16.
After a quick check, I can see that GMP does not have a gmp_not()
function either. I guess the problem is that not
may not make a lot of sense on an arbitrary-length integer.
Say for example you're inverting 00010101
, you'll get 11101010
.
But if you invert 00000000 00010101
(which is the same number as far as BigInteger
is concerned), you'll get 11111111 11101010
, which is a totally different number.
As such, this may not be a desirable addition to BigInteger
?
from math.
Note that Java's BigInteger
does have a not()
method:
https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html#not--
I'd be interested to dig into what it returns. I would suspect this performs the operation on a whole number of bytes, this number being the smallest number that fits the value.
from math.
I have found this implementation in another library:
https://github.com/pear/Math_BigInteger/blob/trunk/Math/BigInteger.php#L2890
from math.
I'm actually trying to replicate RPG's %BITNOT, so not sure it's the same as Java's. I will see if I can do some tests.
from math.
%BITNOT
seems to operate on fixed size numbers, so with no ambiguity.
Doing a NOT on an arbitrary-size integer will always lead to ambiguity: there is no unique answer.
If anything, I'd prefer to be compatible with Java's BigInteger. Hopefully this would fulfil your needs; but I'm not sure I want to go this route.
Otherwise, the solution would maybe be to create a fixed-size integer class, like FixedBigInteger
, that would have a predefined length in bytes.
from math.
Any update here?
from math.
Hey there, good timing! We put the %BITNOT
implementation on the side for now but you were right. We are having to deal with fixed length numbers in our project, since we are porting many algorithms from RPG.
For example, right now we are working on porting algorithms that work with the concept of RPG/Cobol "data structures", which are structs that can share memory space and remap those spaces to different types; evidently the size in bytes is something we have to take into account.
We are planning to apply the concept of byte streams to work around that. Fixed types, like FixedBigInteger
could be an interesting tool for us and I may be able to help developing them if you feel they could be a good addition to the library.
from math.
Thanks for the feedback!
Meanwhile I checked Java's implementation, and it looks like they're doing bit arithmetic on the minimum number of bits that fit the number. The result is a negative number. I don't know if there's any use case for this, and I prefer not to venture into an implementation until someone proves to me that this use case exists.
That being said, I'd be happy with a FixedBigInteger
, with an arbitrary size of $n
bits, and implement bitwise operations, including NOT
, there!
from math.
Something just came up to my mind, we could also pass the number of desired bits in not
:
function not(int $bits) : BigInteger
But I still consider it more or less a hack. Also, that doesn't tell us if the result should be a negative or positive number, so I guess it makes more sense to create explicit classes like FixedSignedBigInteger
and FixedUnsignedBigInteger
, that will leave no ambiguity as to whether the sign of the result should change!
from math.
Yes, I agree fixed types and explicit signed/unsigned ones make more sense.
Regarding our memory mapping problem, I have been playing with the nelexa/buffer package and the concept of buffers has been working well so far during prototyping. If we could introduce fixed types, it would allow us to get their byte representation nicely into the buffer.
from math.
I just checked Java's BigInteger.not()
implementation in more detail, and the not()
operation always returns a number that fits in the same number of bytes as the original number, i.e. if the number fits in 10 bytes, the result will be the two's complement on 10 bytes.
This can be implemented as:
public function not() : BigInteger
{
return self::fromBytes(~ $this->toBytes());
}
But this is actually equal to the negated number, minus 1. As such, the implementation can be simplified as:
public function not() : BigInteger
{
return $this->negated()->minus(1);
}
Both of these implementations return the same results as Java's BigInteger does.
@luiz-brandao-jr could you please tell me if this implementation would be of any use for your use case?
I would be tempted to implement this not()
method right now, to be consistent with Java, but I'd be curious to know if there are any real-life use cases for this one!
from math.
Say for example you're inverting
00010101
, you'll get11101010
.
But if you invert00000000 00010101
(which is the same number as far as BigInteger is concerned), you'll get11111111 11101010
, which is a totally different number.
Actually, wrapping my head around that, I'm starting to realize my mistake. In two's complement representation, 11111111 11101010
is the same number as 11101010
(extra leading 1
s are to negative numbers what leading 0
s are to positive numbers).
So the number of bits on which you're working does not matter: whatever the number of bits, the bitwise NOT
of a number will always be equal to (- number - 1)
, and Java's implementation makes perfect sense.
from math.
Implemented as BigInteger::not()
and released as 0.9.1! 🎉
from math.
Hi @BenMorel that's great news. I think we will definitely have a use case for this one.
We have a constraint right now where we are running PHP compiled at 32-bit, so some numeric values coming from the database could overflow an integer. Although rare, we could also potentially face the same issue with PHP 64-bit since we have some database fields that could store up to 8-byte unsigned integers. This is the reason we started using BigIntegers. And so it happens that some of the algorithms we are porting use bitwise functions!
from math.
@BenMorel one thing that might be an issue for us is that sometimes we use a BigInteger to represent an unsigned integer. This implementation will always return a signed value. I guess we will need to do some manipulation on our end to go around that.
from math.
@luiz-brandao-jr How do you get your value out of the database? As a numeric string? Can you please give an example of where using a signed BigInteger is problematic?
from math.
@BenMorel yes, we get the value as a numeric string from the database but we can also get data from byte streams/buffers.
Example:
Let's say we get a 2-byte unsigned integer from a stream, let's say 7
(this is to make it simple, but in our case it could go up to 8-byte numbers). If we use BigInteger::of('7')->not()
we get -8
, but with a 2-byte unsigned it should be 65528
(11111111 11111000
). But fundamentally it's because we are dealing with fixed sized values, and it's probably up to us to manipulate it.
from math.
but we can also get data from byte streams/buffers.
By the way, in the latest version you have a fromBytes()
factory method that can read binary data out of a string, either signed or unsigned!
from math.
Great, I will take a look at fromBytes
. Merci.
from math.
Related Issues (20)
- GitHub CI instead of Travis HOT 4
- brick/math method for gmp_random_range HOT 4
- brick/math method for gmp_invert HOT 8
- The given value ".1200" does not represent a valid number. HOT 2
- Add a changelog HOT 3
- Rounding error on exactlyDividedBy() HOT 2
- Fatal error: Maximum execution time of 30 seconds exceeded HOT 2
- RFC: add `getPrecision` method. HOT 11
- Issue with dividedBy and MultipliedBy? HOT 3
- Feature Request: Implement lisachenko/z-engine HOT 1
- BigComplex HOT 2
- How to accept any scale without rounding HOT 1
- Accept hexadecimal input HOT 1
- Rounding is necessary to represent the result of the operation at this scale. HOT 2
- [0.10.0] behavior change HOT 1
- Please support php8.1 HOT 1
- Implements the Serializable interface, which is deprecated HOT 1
- `gmp_export` equivalent HOT 6
- Rounding bug, or am I just dumb? HOT 4
- Output a BigRational in decimal form with period
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from math.