Playing with integers, I am surprised that even when i**2 overflows, the compiler may still give 2*i-1 for i**2-(i-1)**2, as this program shows.
program main
implicit none
integer, parameter :: imin = huge(1)/10, imax = huge(imin)-1
integer :: i,j,k,jk
logical, parameter :: print_all = .false.
print "(*(a18))","i","2*i-1","(i**2)-(i-1)**2","j=i**2","k=(i-1)**2","j-k"
do i=imin,imax
j = i**2
k = (i-1)**2
jk = j - k
if (print_all .or. i==imin .or. i==imax) &
print "(*(1x,i17))",i,2*i-1,i**2 - (i-1)**2,j,k,jk
if (jk /= (2*i-1)) stop "here"
end do
end program main
output:
i 2*i-1 (i**2)-(i-1)**2 j=i**2 k=(i-1)**2 j-k
214748364 429496727 429496727 687194768 257698041 429496727
2147483646 -5 -5 4 9 -5
Playing with integers, I am surprised that even when i**2 overflows, the compiler may still give 2*i-1 for i**2-(i-1)**2, as this program shows.
program main
implicit none
integer, parameter :: imin = huge(1)/10, imax = huge(imin)-1
integer :: i,j,k,jk
logical, parameter :: print_all = .false.
print "(*(a18))","i","2*i-1","(i**2)-(i-1)**2","j=i**2","k=(i-1)**2","j-k"
do i=imin,imax
j = i**2
k = (i-1)**2
jk = j - k
if (print_all .or. i==imin .or. i==imax) &
print "(*(1x,i17))",i,2*i-1,i**2 - (i-1)**2,j,k,jk
if (jk /= (2*i-1)) stop "here"
end do
end program main
output:
i 2*i-1 (i**2)-(i-1)**2 j=i**2 k=(i-1)**2 j-k
214748364 429496727 429496727 687194768 257698041 429496727
2147483646 -5 -5 4 9 -5
On Thursday, April 14, 2022 at 9:34:54 AM UTC-7, Beliavsky wrote:.
Playing with integers, I am surprised that even when i**2 overflows, the compiler may still give 2*i-1 for i**2-(i-1)**2, as this program shows.
program main
implicit none
integer, parameter :: imin = huge(1)/10, imax = huge(imin)-1
integer :: i,j,k,jk
logical, parameter :: print_all = .false.
print "(*(a18))","i","2*i-1","(i**2)-(i-1)**2","j=i**2","k=(i-1)**2","j-k" do i=imin,imax
j = i**2
k = (i-1)**2
jk = j - k
if (print_all .or. i==imin .or. i==imax) &
print "(*(1x,i17))",i,2*i-1,i**2 - (i-1)**2,j,k,jk
if (jk /= (2*i-1)) stop "here"
end do
end program main
output:
i 2*i-1 (i**2)-(i-1)**2 j=i**2 k=(i-1)**2 j-k
214748364 429496727 429496727 687194768 257698041 429496727
2147483646 -5 -5 4 9 -5
Most hardware now gives the low bits of the full two's complement product..
If they both overflow the same amount, when you subtract then you get
the result that you would get without overflow.
You could put an IF in the loop, and compare them, but I suspect you are right.
Note that in the second case, both are overflowing.
The products give the low 32 bits as two's complement values.
When you subtract, you get the low 32 bits of the difference.
(In both cases, half the time they will have the wrong sign, though.)
It is slightly more interesting on ones' complement hardware.
Most hardware now gives the low bits of the full two's complement product.
The product is positive (see the initial values).
The low-order bits are not 2's complement. They are the
the truncated low-order bits of the positive product.
On Friday, April 15, 2022 at 7:09:56 AM UTC-7, Robin Vowels wrote:.
(snip)
Read carefully:Most hardware now gives the low bits of the full two's complement product.The product is positive (see the initial values).
The low-order bits are not 2's complement. They are the
the truncated low-order bits of the positive product.
Most hardware now gives the low bits of the full two's complement product. That is, (the low bits of) (the full two's complement product)..
That is, multiply them and generate a double length two's complement.
product,
then return the low bits. And yes often enough they have.
a different sign, about half the time.
Maybe I should say it again:.
Most hardware now gives the low bits of the full two's complement product.
They are NOT twos complement products.
The products are ALWAYS positive.
It is only negative values that are represented in twos complement form.
On Friday, April 15, 2022 at 7:39:02 PM UTC-7, Robin Vowels wrote:
.They are NOT twos complement products. [when an integer is squared]
The products are ALWAYS positive.
Two's complement is the representation used on most machines now..
It can represent both negative and positive values. It is still called
two's complement even when the values are positive.
.It is only negative values that are represented in twos complement form.
The "two's complement" operation is used to change the sign of.
a value that is represented in two's complement,
but no, it is not only.
negative values. They are negative when the sign bit is set, and
positive or zero when it isn't.
And, just to be sure, Unisys last I knew still sold some ones' complement machines. There are complications with C on such machines, as
unsigned arithmetic doesn't do what it is supposed to do. And ones' complement machines can also represent negative, positive,
and zero values.
On Saturday, April 16, 2022 at 1:18:40 PM UTC+10, gah4 wrote:
On Friday, April 15, 2022 at 7:39:02 PM UTC-7, Robin Vowels wrote:.
They are NOT twos complement products. [when an integer is squared]
The products are ALWAYS positive.
Two's complement is the representation used on most machines now..
It can represent both negative and positive values. It is still called
two's complement even when the values are positive.
You are mistaken. It is only negative values that are represented
in twos complement form.
This then brings up the lack of an unsigned integer type in fortran. If
all hardware supported two-complement arithmetic, then I think it would
be straightforward to allow this type into the language. Compilers would
need to do little to support the type and its semantics. But those
computers that use different integer representations (e.g.
ones-complement and signed-magnitude), the twos-complement results would
need to be simulated, and that could be expensive and slow. I'm not
familiar with the current C standard, but in the past the C language
punted on this issue by defining results for unsigned arithmetic only
when there is no overflow (i.e. when the high-order bit can be ignored).
If a C compiler happens to give correct results also when there is
overflow (i.e. when the high-order bit comes into play), then that is
great, but it was not required by the language. Fortran could have taken
that same approach, but it didn't.
This issue also arises in the discussions over the decades for fortran
to support an intrinsic bit data type. When those bits are moved between
the bit data type and integer variables, then the meaning of the
high-order bit, or the sign bit, must be accounted for correctly, making portable code difficult to write.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 131 |
Nodes: | 8 (1 / 7) |
Uptime: | 05:49:58 |
Calls: | 2,691 |
Calls today: | 1 |
Files: | 9,234 |
Messages: | 2,256,733 |